mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-28 05:02:25 -04:00
M17 Modulator: copy of NFM modulator
This commit is contained in:
parent
424d072f0c
commit
7e8e1c12fa
@ -61,4 +61,5 @@ endif()
|
||||
|
||||
if (ENABLE_CHANNELTX_MODFREEDV AND CODEC2_FOUND)
|
||||
add_subdirectory(modfreedv)
|
||||
add_subdirectory(modm17)
|
||||
endif(CODEC2_FOUND)
|
||||
|
64
plugins/channeltx/modm17/CMakeLists.txt
Normal file
64
plugins/channeltx/modm17/CMakeLists.txt
Normal file
@ -0,0 +1,64 @@
|
||||
project(modm17)
|
||||
|
||||
set(modm17_SOURCES
|
||||
m17mod.cpp
|
||||
m17modbaseband.cpp
|
||||
m17modsource.cpp
|
||||
m17modplugin.cpp
|
||||
m17modsettings.cpp
|
||||
m17modwebapiadapter.cpp
|
||||
)
|
||||
|
||||
set(modm17_HEADERS
|
||||
m17mod.h
|
||||
m17modbaseband.h
|
||||
m17modsource.h
|
||||
m17modplugin.h
|
||||
m17modsettings.h
|
||||
m17modwebapiadapter.h
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
|
||||
)
|
||||
|
||||
if(NOT SERVER_MODE)
|
||||
set(modm17_SOURCES
|
||||
${modm17_SOURCES}
|
||||
m17modgui.cpp
|
||||
m17modgui.ui
|
||||
)
|
||||
set(modm17_HEADERS
|
||||
${modm17_HEADERS}
|
||||
m17modgui.h
|
||||
)
|
||||
|
||||
set(TARGET_NAME modm17)
|
||||
set(TARGET_LIB "Qt5::Widgets")
|
||||
set(TARGET_LIB_GUI "sdrgui")
|
||||
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
|
||||
else()
|
||||
set(TARGET_NAME modm17srv)
|
||||
set(TARGET_LIB "")
|
||||
set(TARGET_LIB_GUI "")
|
||||
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
|
||||
endif()
|
||||
|
||||
add_library(${TARGET_NAME} SHARED
|
||||
${modm17_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(${TARGET_NAME}
|
||||
Qt5::Core
|
||||
${TARGET_LIB}
|
||||
sdrbase
|
||||
${TARGET_LIB_GUI}
|
||||
swagger
|
||||
)
|
||||
|
||||
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
|
||||
|
||||
# Install debug symbols
|
||||
if (WIN32)
|
||||
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
|
||||
endif()
|
766
plugins/channeltx/modm17/m17mod.cpp
Normal file
766
plugins/channeltx/modm17/m17mod.cpp
Normal file
@ -0,0 +1,766 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 <QTime>
|
||||
#include <QDebug>
|
||||
#include <QMutexLocker>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QBuffer>
|
||||
#include <QThread>
|
||||
|
||||
#include "SWGChannelSettings.h"
|
||||
#include "SWGWorkspaceInfo.h"
|
||||
#include "SWGChannelReport.h"
|
||||
#include "SWGNFMModReport.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "device/deviceapi.h"
|
||||
#include "feature/feature.h"
|
||||
#include "util/db.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "m17modbaseband.h"
|
||||
#include "m17mod.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(M17Mod::MsgConfigureM17Mod, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17Mod::MsgConfigureFileSourceName, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17Mod::MsgConfigureFileSourceSeek, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17Mod::MsgConfigureFileSourceStreamTiming, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17Mod::MsgReportFileSourceStreamData, Message)
|
||||
MESSAGE_CLASS_DEFINITION(M17Mod::MsgReportFileSourceStreamTiming, Message)
|
||||
|
||||
const char* const M17Mod::m_channelIdURI = "sdrangel.channeltx.modm17";
|
||||
const char* const M17Mod::m_channelId = "M17Mod";
|
||||
|
||||
M17Mod::M17Mod(DeviceAPI *deviceAPI) :
|
||||
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
|
||||
m_deviceAPI(deviceAPI),
|
||||
m_settingsMutex(QMutex::Recursive),
|
||||
m_fileSize(0),
|
||||
m_recordLength(0),
|
||||
m_sampleRate(48000)
|
||||
{
|
||||
setObjectName(m_channelId);
|
||||
|
||||
m_thread = new QThread(this);
|
||||
m_basebandSource = new M17ModBaseband();
|
||||
m_basebandSource->setInputFileStream(&m_ifstream);
|
||||
m_basebandSource->setChannel(this);
|
||||
m_basebandSource->moveToThread(m_thread);
|
||||
|
||||
applySettings(m_settings, true);
|
||||
|
||||
m_deviceAPI->addChannelSource(this);
|
||||
m_deviceAPI->addChannelSourceAPI(this);
|
||||
|
||||
m_networkManager = new QNetworkAccessManager();
|
||||
QObject::connect(
|
||||
m_networkManager,
|
||||
&QNetworkAccessManager::finished,
|
||||
this,
|
||||
&M17Mod::networkManagerFinished
|
||||
);
|
||||
}
|
||||
|
||||
M17Mod::~M17Mod()
|
||||
{
|
||||
QObject::disconnect(
|
||||
m_networkManager,
|
||||
&QNetworkAccessManager::finished,
|
||||
this,
|
||||
&M17Mod::networkManagerFinished
|
||||
);
|
||||
delete m_networkManager;
|
||||
m_deviceAPI->removeChannelSourceAPI(this);
|
||||
m_deviceAPI->removeChannelSource(this);
|
||||
delete m_basebandSource;
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
void M17Mod::setDeviceAPI(DeviceAPI *deviceAPI)
|
||||
{
|
||||
if (deviceAPI != m_deviceAPI)
|
||||
{
|
||||
m_deviceAPI->removeChannelSourceAPI(this);
|
||||
m_deviceAPI->removeChannelSource(this);
|
||||
m_deviceAPI = deviceAPI;
|
||||
m_deviceAPI->addChannelSource(this);
|
||||
m_deviceAPI->addChannelSinkAPI(this);
|
||||
}
|
||||
}
|
||||
|
||||
void M17Mod::start()
|
||||
{
|
||||
qDebug("M17Mod::start");
|
||||
m_basebandSource->reset();
|
||||
m_thread->start();
|
||||
}
|
||||
|
||||
void M17Mod::stop()
|
||||
{
|
||||
qDebug("M17Mod::stop");
|
||||
m_thread->exit();
|
||||
m_thread->wait();
|
||||
}
|
||||
|
||||
void M17Mod::pull(SampleVector::iterator& begin, unsigned int nbSamples)
|
||||
{
|
||||
m_basebandSource->pull(begin, nbSamples);
|
||||
}
|
||||
|
||||
void M17Mod::setCenterFrequency(qint64 frequency)
|
||||
{
|
||||
M17ModSettings settings = m_settings;
|
||||
settings.m_inputFrequencyOffset = frequency;
|
||||
applySettings(settings, false);
|
||||
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
MsgConfigureM17Mod *msgToGUI = MsgConfigureM17Mod::create(settings, false);
|
||||
m_guiMessageQueue->push(msgToGUI);
|
||||
}
|
||||
}
|
||||
|
||||
bool M17Mod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureM17Mod::match(cmd))
|
||||
{
|
||||
MsgConfigureM17Mod& cfg = (MsgConfigureM17Mod&) cmd;
|
||||
qDebug() << "M17Mod::handleMessage: MsgConfigureM17Mod";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceName::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
|
||||
m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
qDebug() << "M17Mod::handleMessage: MsgConfigureFileSourceName:"
|
||||
<< " m_fileName: " << m_fileName;
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceSeek::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd;
|
||||
int seekPercentage = conf.getPercentage();
|
||||
seekFileStream(seekPercentage);
|
||||
qDebug() << "M17Mod::handleMessage: MsgConfigureFileSourceSeek:"
|
||||
<< " seekPercentage: " << seekPercentage;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceStreamTiming::match(cmd))
|
||||
{
|
||||
std::size_t samplesCount;
|
||||
|
||||
if (m_ifstream.eof()) {
|
||||
samplesCount = m_fileSize / sizeof(Real);
|
||||
} else {
|
||||
samplesCount = m_ifstream.tellg() / sizeof(Real);
|
||||
}
|
||||
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceName::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) cmd;
|
||||
m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
qDebug() << "M17Mod::handleMessage: MsgConfigureFileSourceName:"
|
||||
<< " m_fileName: " << m_fileName;
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceSeek::match(cmd))
|
||||
{
|
||||
MsgConfigureFileSourceSeek& conf = (MsgConfigureFileSourceSeek&) cmd;
|
||||
int seekPercentage = conf.getPercentage();
|
||||
seekFileStream(seekPercentage);
|
||||
qDebug() << "M17Mod::handleMessage: MsgConfigureFileSourceSeek:"
|
||||
<< " seekPercentage: " << seekPercentage;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceStreamTiming::match(cmd))
|
||||
{
|
||||
std::size_t samplesCount;
|
||||
|
||||
if (m_ifstream.eof()) {
|
||||
samplesCount = m_fileSize / sizeof(Real);
|
||||
} else {
|
||||
samplesCount = m_ifstream.tellg() / sizeof(Real);
|
||||
}
|
||||
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
report = MsgReportFileSourceStreamTiming::create(samplesCount);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
// Forward to the source
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
DSPSignalNotification* rep = new DSPSignalNotification(notif); // make a copy
|
||||
qDebug() << "M17Mod::handleMessage: DSPSignalNotification";
|
||||
m_basebandSource->getInputMessageQueue()->push(rep);
|
||||
// Forward to GUI if any
|
||||
if (getMessageQueueToGUI()) {
|
||||
getMessageQueueToGUI()->push(new DSPSignalNotification(notif));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MainCore::MsgChannelDemodQuery::match(cmd))
|
||||
{
|
||||
qDebug() << "M17Mod::handleMessage: MsgChannelDemodQuery";
|
||||
sendSampleRateToDemodAnalyzer();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void M17Mod::openFileStream()
|
||||
{
|
||||
if (m_ifstream.is_open()) {
|
||||
m_ifstream.close();
|
||||
}
|
||||
|
||||
m_ifstream.open(m_fileName.toStdString().c_str(), std::ios::binary | std::ios::ate);
|
||||
m_fileSize = m_ifstream.tellg();
|
||||
m_ifstream.seekg(0,std::ios_base::beg);
|
||||
|
||||
m_sampleRate = 48000; // fixed rate
|
||||
m_recordLength = m_fileSize / (sizeof(Real) * m_sampleRate);
|
||||
|
||||
qDebug() << "M17Mod::openFileStream: " << m_fileName.toStdString().c_str()
|
||||
<< " fileSize: " << m_fileSize << "bytes"
|
||||
<< " length: " << m_recordLength << " seconds";
|
||||
|
||||
MsgReportFileSourceStreamData *report;
|
||||
report = MsgReportFileSourceStreamData::create(m_sampleRate, m_recordLength);
|
||||
getMessageQueueToGUI()->push(report);
|
||||
}
|
||||
|
||||
void M17Mod::seekFileStream(int seekPercentage)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_settingsMutex);
|
||||
|
||||
if (m_ifstream.is_open())
|
||||
{
|
||||
int seekPoint = ((m_recordLength * seekPercentage) / 100) * m_sampleRate;
|
||||
seekPoint *= sizeof(Real);
|
||||
m_ifstream.clear();
|
||||
m_ifstream.seekg(seekPoint, std::ios::beg);
|
||||
}
|
||||
}
|
||||
|
||||
void M17Mod::applySettings(const M17ModSettings& settings, bool force)
|
||||
{
|
||||
qDebug() << "M17Mod::applySettings:"
|
||||
<< " m_inputFrequencyOffset: " << settings.m_inputFrequencyOffset
|
||||
<< " m_rfBandwidth: " << settings.m_rfBandwidth
|
||||
<< " m_fmDeviation: " << settings.m_fmDeviation
|
||||
<< " m_volumeFactor: " << settings.m_volumeFactor
|
||||
<< " m_toneFrequency: " << settings.m_toneFrequency
|
||||
<< " m_channelMute: " << settings.m_channelMute
|
||||
<< " m_playLoop: " << settings.m_playLoop
|
||||
<< " m_modAFInput " << settings.m_modAFInput
|
||||
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||
<< " m_useReverseAPI: " << settings.m_useReverseAPI
|
||||
<< " m_reverseAPIAddress: " << settings.m_reverseAPIAddress
|
||||
<< " m_reverseAPIAddress: " << settings.m_reverseAPIPort
|
||||
<< " m_reverseAPIDeviceIndex: " << settings.m_reverseAPIDeviceIndex
|
||||
<< " m_reverseAPIChannelIndex: " << settings.m_reverseAPIChannelIndex
|
||||
<< " force: " << force;
|
||||
|
||||
QList<QString> reverseAPIKeys;
|
||||
|
||||
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force) {
|
||||
reverseAPIKeys.append("inputFrequencyOffset");
|
||||
}
|
||||
if ((settings.m_fmDeviation != m_settings.m_fmDeviation) || force) {
|
||||
reverseAPIKeys.append("fmDeviation");
|
||||
}
|
||||
if ((settings.m_volumeFactor != m_settings.m_volumeFactor) || force) {
|
||||
reverseAPIKeys.append("volumeFactor");
|
||||
}
|
||||
if ((settings.m_channelMute != m_settings.m_channelMute) || force) {
|
||||
reverseAPIKeys.append("channelMute");
|
||||
}
|
||||
if ((settings.m_playLoop != m_settings.m_playLoop) || force) {
|
||||
reverseAPIKeys.append("playLoop");
|
||||
}
|
||||
if ((settings.m_modAFInput != m_settings.m_modAFInput) || force) {
|
||||
reverseAPIKeys.append("modAFInput");
|
||||
}
|
||||
if((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force) {
|
||||
reverseAPIKeys.append("rfBandwidth");
|
||||
}
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
|
||||
reverseAPIKeys.append("toneFrequency");
|
||||
}
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force) {
|
||||
reverseAPIKeys.append("audioDeviceName");
|
||||
}
|
||||
if ((settings.m_feedbackAudioDeviceName != m_settings.m_feedbackAudioDeviceName) || force) {
|
||||
reverseAPIKeys.append("feedbackAudioDeviceName");
|
||||
}
|
||||
|
||||
if (m_settings.m_streamIndex != settings.m_streamIndex)
|
||||
{
|
||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
||||
{
|
||||
m_deviceAPI->removeChannelSourceAPI(this);
|
||||
m_deviceAPI->removeChannelSource(this, m_settings.m_streamIndex);
|
||||
m_deviceAPI->addChannelSource(this, settings.m_streamIndex);
|
||||
m_deviceAPI->addChannelSourceAPI(this);
|
||||
}
|
||||
|
||||
reverseAPIKeys.append("streamIndex");
|
||||
}
|
||||
|
||||
M17ModBaseband::MsgConfigureM17ModBaseband *msg = M17ModBaseband::MsgConfigureM17ModBaseband::create(settings, force);
|
||||
m_basebandSource->getInputMessageQueue()->push(msg);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "settings", pipes);
|
||||
|
||||
if (pipes.size() > 0) {
|
||||
sendChannelSettings(pipes, reverseAPIKeys, settings, force);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
QByteArray M17Mod::serialize() const
|
||||
{
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool M17Mod::deserialize(const QByteArray& data)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if (!m_settings.deserialize(data))
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
success = false;
|
||||
}
|
||||
|
||||
MsgConfigureM17Mod *msg = MsgConfigureM17Mod::create(m_settings, true);
|
||||
m_inputMessageQueue.push(msg);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void M17Mod::sendSampleRateToDemodAnalyzer()
|
||||
{
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(this, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
MessageQueue* messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(
|
||||
this,
|
||||
getAudioSampleRate()
|
||||
);
|
||||
messageQueue->push(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int M17Mod::webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setM17ModSettings(new SWGSDRangel::SWGM17ModSettings());
|
||||
response.getM17ModSettings()->init();
|
||||
webapiFormatChannelSettings(response, m_settings);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int M17Mod::webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setIndex(m_settings.m_workspaceIndex);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int M17Mod::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
M17ModSettings settings = m_settings;
|
||||
webapiUpdateChannelSettings(settings, channelSettingsKeys, response);
|
||||
|
||||
MsgConfigureM17Mod *msg = MsgConfigureM17Mod::create(settings, force);
|
||||
m_inputMessageQueue.push(msg);
|
||||
|
||||
if (m_guiMessageQueue) // forward to GUI if any
|
||||
{
|
||||
MsgConfigureM17Mod *msgToGUI = MsgConfigureM17Mod::create(settings, force);
|
||||
m_guiMessageQueue->push(msgToGUI);
|
||||
}
|
||||
|
||||
webapiFormatChannelSettings(response, settings);
|
||||
|
||||
return 200;
|
||||
}
|
||||
|
||||
void M17Mod::webapiUpdateChannelSettings(
|
||||
M17ModSettings& settings,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response)
|
||||
{
|
||||
if (channelSettingsKeys.contains("channelMute")) {
|
||||
settings.m_channelMute = response.getM17ModSettings()->getChannelMute() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("fmDeviation")) {
|
||||
settings.m_fmDeviation = response.getM17ModSettings()->getFmDeviation();
|
||||
}
|
||||
if (channelSettingsKeys.contains("inputFrequencyOffset")) {
|
||||
settings.m_inputFrequencyOffset = response.getM17ModSettings()->getInputFrequencyOffset();
|
||||
}
|
||||
if (channelSettingsKeys.contains("modAFInput")) {
|
||||
settings.m_modAFInput = (M17ModSettings::M17ModInputAF) response.getM17ModSettings()->getModAfInput();
|
||||
}
|
||||
if (channelSettingsKeys.contains("playLoop")) {
|
||||
settings.m_playLoop = response.getM17ModSettings()->getPlayLoop() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("rfBandwidth")) {
|
||||
settings.m_rfBandwidth = response.getM17ModSettings()->getRfBandwidth();
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor")) {
|
||||
settings.m_rgbColor = response.getM17ModSettings()->getRgbColor();
|
||||
}
|
||||
if (channelSettingsKeys.contains("title")) {
|
||||
settings.m_title = *response.getM17ModSettings()->getTitle();
|
||||
}
|
||||
if (channelSettingsKeys.contains("toneFrequency")) {
|
||||
settings.m_toneFrequency = response.getM17ModSettings()->getToneFrequency();
|
||||
}
|
||||
if (channelSettingsKeys.contains("volumeFactor")) {
|
||||
settings.m_volumeFactor = response.getM17ModSettings()->getVolumeFactor();
|
||||
}
|
||||
if (channelSettingsKeys.contains("streamIndex")) {
|
||||
settings.m_streamIndex = response.getM17ModSettings()->getStreamIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("useReverseAPI")) {
|
||||
settings.m_useReverseAPI = response.getM17ModSettings()->getUseReverseApi() != 0;
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIAddress")) {
|
||||
settings.m_reverseAPIAddress = *response.getM17ModSettings()->getReverseApiAddress();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIPort")) {
|
||||
settings.m_reverseAPIPort = response.getM17ModSettings()->getReverseApiPort();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
|
||||
settings.m_reverseAPIDeviceIndex = response.getM17ModSettings()->getReverseApiDeviceIndex();
|
||||
}
|
||||
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
|
||||
settings.m_reverseAPIChannelIndex = response.getNfmModSettings()->getReverseApiChannelIndex();
|
||||
}
|
||||
if (settings.m_channelMarker && channelSettingsKeys.contains("channelMarker")) {
|
||||
settings.m_channelMarker->updateFrom(channelSettingsKeys, response.getM17ModSettings()->getChannelMarker());
|
||||
}
|
||||
if (settings.m_rollupState && channelSettingsKeys.contains("rollupState")) {
|
||||
settings.m_rollupState->updateFrom(channelSettingsKeys, response.getM17ModSettings()->getRollupState());
|
||||
}
|
||||
}
|
||||
|
||||
int M17Mod::webapiReportGet(
|
||||
SWGSDRangel::SWGChannelReport& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setM17ModReport(new SWGSDRangel::SWGM17ModReport());
|
||||
response.getM17ModReport()->init();
|
||||
webapiFormatChannelReport(response);
|
||||
return 200;
|
||||
}
|
||||
|
||||
void M17Mod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const M17ModSettings& settings)
|
||||
{
|
||||
response.getM17ModSettings()->setChannelMute(settings.m_channelMute ? 1 : 0);
|
||||
response.getM17ModSettings()->setFmDeviation(settings.m_fmDeviation);
|
||||
response.getM17ModSettings()->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
|
||||
response.getM17ModSettings()->setModAfInput((int) settings.m_modAFInput);
|
||||
response.getM17ModSettings()->setPlayLoop(settings.m_playLoop ? 1 : 0);
|
||||
response.getM17ModSettings()->setRfBandwidth(settings.m_rfBandwidth);
|
||||
response.getM17ModSettings()->setRgbColor(settings.m_rgbColor);
|
||||
|
||||
if (response.getM17ModSettings()->getTitle()) {
|
||||
*response.getM17ModSettings()->getTitle() = settings.m_title;
|
||||
} else {
|
||||
response.getM17ModSettings()->setTitle(new QString(settings.m_title));
|
||||
}
|
||||
|
||||
response.getM17ModSettings()->setToneFrequency(settings.m_toneFrequency);
|
||||
response.getM17ModSettings()->setVolumeFactor(settings.m_volumeFactor);
|
||||
|
||||
if (response.getM17ModSettings()->getAudioDeviceName()) {
|
||||
*response.getM17ModSettings()->getAudioDeviceName() = settings.m_audioDeviceName;
|
||||
} else {
|
||||
response.getM17ModSettings()->setAudioDeviceName(new QString(settings.m_audioDeviceName));
|
||||
}
|
||||
|
||||
response.getM17ModSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
|
||||
|
||||
if (response.getM17ModSettings()->getReverseApiAddress()) {
|
||||
*response.getM17ModSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
|
||||
} else {
|
||||
response.getM17ModSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
|
||||
}
|
||||
|
||||
response.getM17ModSettings()->setReverseApiPort(settings.m_reverseAPIPort);
|
||||
response.getM17ModSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
|
||||
response.getM17ModSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
|
||||
|
||||
if (settings.m_channelMarker)
|
||||
{
|
||||
if (response.getM17ModSettings()->getChannelMarker())
|
||||
{
|
||||
settings.m_channelMarker->formatTo(response.getM17ModSettings()->getChannelMarker());
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
response.getM17ModSettings()->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.m_rollupState)
|
||||
{
|
||||
if (response.getM17ModSettings()->getRollupState())
|
||||
{
|
||||
settings.m_rollupState->formatTo(response.getM17ModSettings()->getRollupState());
|
||||
}
|
||||
else
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
response.getM17ModSettings()->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M17Mod::webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response)
|
||||
{
|
||||
response.getM17ModReport()->setChannelPowerDb(CalcDb::dbPower(getMagSq()));
|
||||
response.getM17ModReport()->setAudioSampleRate(m_basebandSource->getAudioSampleRate());
|
||||
response.getM17ModReport()->setChannelSampleRate(m_basebandSource->getChannelSampleRate());
|
||||
}
|
||||
|
||||
void M17Mod::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const M17ModSettings& settings, bool force)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
|
||||
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
|
||||
QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
|
||||
buffer->setParent(reply);
|
||||
|
||||
delete swgChannelSettings;
|
||||
}
|
||||
|
||||
void M17Mod::sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const M17ModSettings& settings,
|
||||
bool force)
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||
|
||||
if (messageQueue)
|
||||
{
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
|
||||
webapiFormatChannelSettings(channelSettingsKeys, swgChannelSettings, settings, force);
|
||||
MainCore::MsgChannelSettings *msg = MainCore::MsgChannelSettings::create(
|
||||
this,
|
||||
channelSettingsKeys,
|
||||
swgChannelSettings,
|
||||
force
|
||||
);
|
||||
messageQueue->push(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M17Mod::webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const M17ModSettings& settings,
|
||||
bool force
|
||||
)
|
||||
{
|
||||
swgChannelSettings->setDirection(1); // single source (Tx)
|
||||
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
|
||||
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
|
||||
swgChannelSettings->setChannelType(new QString(m_channelId));
|
||||
swgChannelSettings->setM17ModSettings(new SWGSDRangel::SWGM17ModSettings());
|
||||
SWGSDRangel::SWGM17ModSettings *swgM17ModSettings = swgChannelSettings->getM17ModSettings();
|
||||
|
||||
// transfer data that has been modified. When force is on transfer all data except reverse API data
|
||||
|
||||
if (channelSettingsKeys.contains("channelMute") || force) {
|
||||
swgM17ModSettings->setChannelMute(settings.m_channelMute ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("inputFrequencyOffset") || force) {
|
||||
swgM17ModSettings->setInputFrequencyOffset(settings.m_inputFrequencyOffset);
|
||||
}
|
||||
if (channelSettingsKeys.contains("modAFInput") || force) {
|
||||
swgM17ModSettings->setModAfInput((int) settings.m_modAFInput);
|
||||
}
|
||||
if (channelSettingsKeys.contains("audioDeviceName") || force) {
|
||||
swgM17ModSettings->setAudioDeviceName(new QString(settings.m_audioDeviceName));
|
||||
}
|
||||
if (channelSettingsKeys.contains("playLoop") || force) {
|
||||
swgM17ModSettings->setPlayLoop(settings.m_playLoop ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("fmDeviation") || force) {
|
||||
swgM17ModSettings->setFmDeviation(settings.m_fmDeviation);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rfBandwidth") || force) {
|
||||
swgM17ModSettings->setRfBandwidth(settings.m_rfBandwidth);
|
||||
}
|
||||
if (channelSettingsKeys.contains("rgbColor") || force) {
|
||||
swgM17ModSettings->setRgbColor(settings.m_rgbColor);
|
||||
}
|
||||
if (channelSettingsKeys.contains("title") || force) {
|
||||
swgM17ModSettings->setTitle(new QString(settings.m_title));
|
||||
}
|
||||
if (channelSettingsKeys.contains("toneFrequency") || force) {
|
||||
swgM17ModSettings->setToneFrequency(settings.m_toneFrequency);
|
||||
}
|
||||
if (channelSettingsKeys.contains("volumeFactor") || force) {
|
||||
swgM17ModSettings->setVolumeFactor(settings.m_volumeFactor);
|
||||
}
|
||||
if (channelSettingsKeys.contains("streamIndex") || force) {
|
||||
swgM17ModSettings->setStreamIndex(settings.m_streamIndex);
|
||||
}
|
||||
|
||||
if (settings.m_channelMarker && (channelSettingsKeys.contains("channelMarker") || force))
|
||||
{
|
||||
SWGSDRangel::SWGChannelMarker *swgChannelMarker = new SWGSDRangel::SWGChannelMarker();
|
||||
settings.m_channelMarker->formatTo(swgChannelMarker);
|
||||
swgM17ModSettings->setChannelMarker(swgChannelMarker);
|
||||
}
|
||||
|
||||
if (settings.m_rollupState && (channelSettingsKeys.contains("rollupState") || force))
|
||||
{
|
||||
SWGSDRangel::SWGRollupState *swgRollupState = new SWGSDRangel::SWGRollupState();
|
||||
settings.m_rollupState->formatTo(swgRollupState);
|
||||
swgM17ModSettings->setRollupState(swgRollupState);
|
||||
}
|
||||
}
|
||||
|
||||
void M17Mod::networkManagerFinished(QNetworkReply *reply)
|
||||
{
|
||||
QNetworkReply::NetworkError replyError = reply->error();
|
||||
|
||||
if (replyError)
|
||||
{
|
||||
qWarning() << "M17Mod::networkManagerFinished:"
|
||||
<< " error(" << (int) replyError
|
||||
<< "): " << replyError
|
||||
<< ": " << reply->errorString();
|
||||
}
|
||||
else
|
||||
{
|
||||
QString answer = reply->readAll();
|
||||
answer.chop(1); // remove last \n
|
||||
qDebug("M17Mod::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
double M17Mod::getMagSq() const
|
||||
{
|
||||
return m_basebandSource->getMagSq();
|
||||
}
|
||||
|
||||
void M17Mod::setLevelMeter(QObject *levelMeter)
|
||||
{
|
||||
connect(m_basebandSource, SIGNAL(levelChanged(qreal, qreal, int)), levelMeter, SLOT(levelChanged(qreal, qreal, int)));
|
||||
}
|
||||
|
||||
uint32_t M17Mod::getNumberOfDeviceStreams() const
|
||||
{
|
||||
return m_deviceAPI->getNbSinkStreams();
|
||||
}
|
||||
|
||||
int M17Mod::getAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getAudioSampleRate();
|
||||
}
|
||||
|
||||
int M17Mod::getFeedbackAudioSampleRate() const
|
||||
{
|
||||
return m_basebandSource->getFeedbackAudioSampleRate();
|
||||
}
|
288
plugins/channeltx/modm17/m17mod.h
Normal file
288
plugins/channeltx/modm17/m17mod.h
Normal file
@ -0,0 +1,288 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_CHANNELTX_MODM17_M17MOD_H_
|
||||
#define PLUGINS_CHANNELTX_MODM17_M17MOD_H_
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "dsp/basebandsamplesource.h"
|
||||
#include "channel/channelapi.h"
|
||||
#include "util/message.h"
|
||||
|
||||
#include "m17modsettings.h"
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QThread;
|
||||
class DeviceAPI;
|
||||
class M17ModBaseband;
|
||||
class ObjectPipe;
|
||||
|
||||
class M17Mod : public BasebandSampleSource, public ChannelAPI {
|
||||
public:
|
||||
class MsgConfigureM17Mod : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const M17ModSettings& getSettings() const { return m_settings; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureM17Mod* create(const M17ModSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureM17Mod(settings, force);
|
||||
}
|
||||
|
||||
private:
|
||||
M17ModSettings m_settings;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureM17Mod(const M17ModSettings& settings, bool force) :
|
||||
Message(),
|
||||
m_settings(settings),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgConfigureFileSourceName : public Message
|
||||
{
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const QString& getFileName() const { return m_fileName; }
|
||||
|
||||
static MsgConfigureFileSourceName* create(const QString& fileName)
|
||||
{
|
||||
return new MsgConfigureFileSourceName(fileName);
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_fileName;
|
||||
|
||||
MsgConfigureFileSourceName(const QString& fileName) :
|
||||
Message(),
|
||||
m_fileName(fileName)
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgConfigureFileSourceSeek : public Message
|
||||
{
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getPercentage() const { return m_seekPercentage; }
|
||||
|
||||
static MsgConfigureFileSourceSeek* create(int seekPercentage)
|
||||
{
|
||||
return new MsgConfigureFileSourceSeek(seekPercentage);
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_seekPercentage; //!< percentage of seek position from the beginning 0..100
|
||||
|
||||
MsgConfigureFileSourceSeek(int seekPercentage) :
|
||||
Message(),
|
||||
m_seekPercentage(seekPercentage)
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgConfigureFileSourceStreamTiming : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
|
||||
static MsgConfigureFileSourceStreamTiming* create()
|
||||
{
|
||||
return new MsgConfigureFileSourceStreamTiming();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
MsgConfigureFileSourceStreamTiming() :
|
||||
Message()
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgReportFileSourceStreamTiming : public Message
|
||||
{
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
std::size_t getSamplesCount() const { return m_samplesCount; }
|
||||
|
||||
static MsgReportFileSourceStreamTiming* create(std::size_t samplesCount)
|
||||
{
|
||||
return new MsgReportFileSourceStreamTiming(samplesCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::size_t m_samplesCount;
|
||||
|
||||
MsgReportFileSourceStreamTiming(std::size_t samplesCount) :
|
||||
Message(),
|
||||
m_samplesCount(samplesCount)
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgReportFileSourceStreamData : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
int getSampleRate() const { return m_sampleRate; }
|
||||
quint32 getRecordLength() const { return m_recordLength; }
|
||||
|
||||
static MsgReportFileSourceStreamData* create(int sampleRate,
|
||||
quint32 recordLength)
|
||||
{
|
||||
return new MsgReportFileSourceStreamData(sampleRate, recordLength);
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_sampleRate;
|
||||
quint32 m_recordLength;
|
||||
|
||||
MsgReportFileSourceStreamData(int sampleRate,
|
||||
quint32 recordLength) :
|
||||
Message(),
|
||||
m_sampleRate(sampleRate),
|
||||
m_recordLength(recordLength)
|
||||
{ }
|
||||
};
|
||||
|
||||
//=================================================================
|
||||
|
||||
M17Mod(DeviceAPI *deviceAPI);
|
||||
virtual ~M17Mod();
|
||||
virtual void destroy() { delete this; }
|
||||
virtual void setDeviceAPI(DeviceAPI *deviceAPI);
|
||||
virtual DeviceAPI *getDeviceAPI() { return m_deviceAPI; }
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void pull(SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
virtual void pushMessage(Message *msg) { m_inputMessageQueue.push(msg); }
|
||||
virtual QString getSourceName() { return objectName(); }
|
||||
|
||||
virtual void getIdentifier(QString& id) { id = objectName(); }
|
||||
virtual QString getIdentifier() const { return objectName(); }
|
||||
virtual void getTitle(QString& title) { title = m_settings.m_title; }
|
||||
virtual qint64 getCenterFrequency() const { return m_settings.m_inputFrequencyOffset; }
|
||||
virtual void setCenterFrequency(qint64 frequency);
|
||||
|
||||
virtual QByteArray serialize() const;
|
||||
virtual bool deserialize(const QByteArray& data);
|
||||
|
||||
virtual int getNbSinkStreams() const { return 1; }
|
||||
virtual int getNbSourceStreams() const { return 0; }
|
||||
|
||||
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
|
||||
{
|
||||
(void) streamIndex;
|
||||
(void) sinkElseSource;
|
||||
return m_settings.m_inputFrequencyOffset;
|
||||
}
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiWorkspaceGet(
|
||||
SWGSDRangel::SWGWorkspaceInfo& 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 void webapiFormatChannelSettings(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
const M17ModSettings& settings);
|
||||
|
||||
static void webapiUpdateChannelSettings(
|
||||
M17ModSettings& settings,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response);
|
||||
|
||||
double getMagSq() const;
|
||||
void setLevelMeter(QObject *levelMeter);
|
||||
uint32_t getNumberOfDeviceStreams() const;
|
||||
int getAudioSampleRate() const;
|
||||
int getFeedbackAudioSampleRate() const;
|
||||
|
||||
static const char* const m_channelIdURI;
|
||||
static const char* const m_channelId;
|
||||
|
||||
private:
|
||||
enum RateState {
|
||||
RSInitialFill,
|
||||
RSRunning
|
||||
};
|
||||
|
||||
DeviceAPI* m_deviceAPI;
|
||||
QThread *m_thread;
|
||||
M17ModBaseband* m_basebandSource;
|
||||
M17ModSettings m_settings;
|
||||
|
||||
SampleVector m_sampleBuffer;
|
||||
QMutex m_settingsMutex;
|
||||
|
||||
std::ifstream m_ifstream;
|
||||
QString m_fileName;
|
||||
quint64 m_fileSize; //!< raw file size (bytes)
|
||||
quint32 m_recordLength; //!< record length in seconds computed from file size
|
||||
int m_sampleRate;
|
||||
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QNetworkRequest m_networkRequest;
|
||||
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
void applySettings(const M17ModSettings& settings, bool force = false);
|
||||
void sendSampleRateToDemodAnalyzer();
|
||||
void openFileStream();
|
||||
void seekFileStream(int seekPercentage);
|
||||
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
|
||||
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const M17ModSettings& settings, bool force);
|
||||
void sendChannelSettings(
|
||||
const QList<ObjectPipe*>& pipes,
|
||||
QList<QString>& channelSettingsKeys,
|
||||
const M17ModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
void webapiFormatChannelSettings(
|
||||
QList<QString>& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings *swgChannelSettings,
|
||||
const M17ModSettings& settings,
|
||||
bool force
|
||||
);
|
||||
|
||||
private slots:
|
||||
void networkManagerFinished(QNetworkReply *reply);
|
||||
};
|
||||
|
||||
|
||||
#endif /* PLUGINS_CHANNELTX_MODM17_M17MOD_H_ */
|
232
plugins/channeltx/modm17/m17modbaseband.cpp
Normal file
232
plugins/channeltx/modm17/m17modbaseband.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 <QDebug>
|
||||
|
||||
#include "dsp/upchannelizer.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
|
||||
#include "m17modbaseband.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(M17ModBaseband::MsgConfigureM17ModBaseband, Message)
|
||||
|
||||
M17ModBaseband::M17ModBaseband() :
|
||||
m_mutex(QMutex::Recursive)
|
||||
{
|
||||
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(48000));
|
||||
m_channelizer = new UpChannelizer(&m_source);
|
||||
|
||||
qDebug("M17ModBaseband::M17ModBaseband");
|
||||
QObject::connect(
|
||||
&m_sampleFifo,
|
||||
&SampleSourceFifo::dataRead,
|
||||
this,
|
||||
&M17ModBaseband::handleData,
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
|
||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(m_source.getFeedbackAudioFifo(), getInputMessageQueue());
|
||||
m_source.applyFeedbackAudioSampleRate(DSPEngine::instance()->getAudioDeviceManager()->getOutputSampleRate());
|
||||
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
}
|
||||
|
||||
M17ModBaseband::~M17ModBaseband()
|
||||
{
|
||||
DSPEngine::instance()->getAudioDeviceManager()->removeAudioSink(m_source.getFeedbackAudioFifo());
|
||||
DSPEngine::instance()->getAudioDeviceManager()->removeAudioSource(m_source.getAudioFifo());
|
||||
delete m_channelizer;
|
||||
}
|
||||
|
||||
void M17ModBaseband::reset()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
m_sampleFifo.reset();
|
||||
}
|
||||
|
||||
void M17ModBaseband::setChannel(ChannelAPI *channel)
|
||||
{
|
||||
m_source.setChannel(channel);
|
||||
}
|
||||
|
||||
void M17ModBaseband::pull(const SampleVector::iterator& begin, unsigned int nbSamples)
|
||||
{
|
||||
unsigned int part1Begin, part1End, part2Begin, part2End;
|
||||
m_sampleFifo.read(nbSamples, part1Begin, part1End, part2Begin, part2End);
|
||||
SampleVector& data = m_sampleFifo.getData();
|
||||
|
||||
if (part1Begin != part1End)
|
||||
{
|
||||
std::copy(
|
||||
data.begin() + part1Begin,
|
||||
data.begin() + part1End,
|
||||
begin
|
||||
);
|
||||
}
|
||||
|
||||
unsigned int shift = part1End - part1Begin;
|
||||
|
||||
if (part2Begin != part2End)
|
||||
{
|
||||
std::copy(
|
||||
data.begin() + part2Begin,
|
||||
data.begin() + part2End,
|
||||
begin + shift
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModBaseband::handleData()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
SampleVector& data = m_sampleFifo.getData();
|
||||
unsigned int ipart1begin;
|
||||
unsigned int ipart1end;
|
||||
unsigned int ipart2begin;
|
||||
unsigned int ipart2end;
|
||||
qreal rmsLevel, peakLevel;
|
||||
int numSamples;
|
||||
|
||||
unsigned int remainder = m_sampleFifo.remainder();
|
||||
|
||||
while ((remainder > 0) && (m_inputMessageQueue.size() == 0))
|
||||
{
|
||||
m_sampleFifo.write(remainder, ipart1begin, ipart1end, ipart2begin, ipart2end);
|
||||
|
||||
if (ipart1begin != ipart1end) { // first part of FIFO data
|
||||
processFifo(data, ipart1begin, ipart1end);
|
||||
}
|
||||
|
||||
if (ipart2begin != ipart2end) { // second part of FIFO data (used when block wraps around)
|
||||
processFifo(data, ipart2begin, ipart2end);
|
||||
}
|
||||
|
||||
remainder = m_sampleFifo.remainder();
|
||||
}
|
||||
|
||||
m_source.getLevels(rmsLevel, peakLevel, numSamples);
|
||||
emit levelChanged(rmsLevel, peakLevel, numSamples);
|
||||
}
|
||||
|
||||
void M17ModBaseband::processFifo(SampleVector& data, unsigned int iBegin, unsigned int iEnd)
|
||||
{
|
||||
m_channelizer->prefetch(iEnd - iBegin);
|
||||
m_channelizer->pull(data.begin() + iBegin, iEnd - iBegin);
|
||||
}
|
||||
|
||||
void M17ModBaseband::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()) != nullptr)
|
||||
{
|
||||
if (handleMessage(*message)) {
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool M17ModBaseband::handleMessage(const Message& cmd)
|
||||
{
|
||||
if (MsgConfigureM17ModBaseband::match(cmd))
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
MsgConfigureM17ModBaseband& cfg = (MsgConfigureM17ModBaseband&) cmd;
|
||||
qDebug() << "M17ModBaseband::handleMessage: MsgConfigureM17ModBaseband";
|
||||
|
||||
applySettings(cfg.getSettings(), cfg.getForce());
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
qDebug() << "M17ModBaseband::handleMessage: DSPSignalNotification: basebandSampleRate: " << notif.getSampleRate();
|
||||
m_sampleFifo.resize(SampleSourceFifo::getSizePolicy(notif.getSampleRate()));
|
||||
m_channelizer->setBasebandSampleRate(notif.getSampleRate());
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModBaseband::applySettings(const M17ModSettings& settings, bool force)
|
||||
{
|
||||
if ((settings.m_inputFrequencyOffset != m_settings.m_inputFrequencyOffset) || force)
|
||||
{
|
||||
m_channelizer->setChannelization(m_source.getAudioSampleRate(), settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(m_source.getAudioSampleRate()); // reapply in case of channel sample rate change
|
||||
|
||||
}
|
||||
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
int audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getAudioSampleRate() != audioSampleRate)
|
||||
{
|
||||
m_channelizer->setChannelization(audioSampleRate, settings.m_inputFrequencyOffset);
|
||||
m_source.applyChannelSettings(m_channelizer->getChannelSampleRate(), m_channelizer->getChannelFrequencyOffset());
|
||||
m_source.applyAudioSampleRate(audioSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
if ((settings.m_modAFInput != m_settings.m_modAFInput) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
|
||||
if (settings.m_modAFInput == M17ModSettings::M17ModInputAudio) {
|
||||
audioDeviceManager->addAudioSource(getAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
} else {
|
||||
audioDeviceManager->removeAudioSource(getAudioFifo());
|
||||
}
|
||||
}
|
||||
|
||||
if ((settings.m_feedbackAudioDeviceName != m_settings.m_feedbackAudioDeviceName) || force)
|
||||
{
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getOutputDeviceIndex(settings.m_feedbackAudioDeviceName);
|
||||
audioDeviceManager->removeAudioSink(getFeedbackAudioFifo());
|
||||
audioDeviceManager->addAudioSink(getFeedbackAudioFifo(), getInputMessageQueue(), audioDeviceIndex);
|
||||
int audioSampleRate = audioDeviceManager->getOutputSampleRate(audioDeviceIndex);
|
||||
|
||||
if (getFeedbackAudioSampleRate() != audioSampleRate) {
|
||||
m_source.applyFeedbackAudioSampleRate(audioSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
m_source.applySettings(settings, force);
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
int M17ModBaseband::getChannelSampleRate() const
|
||||
{
|
||||
return m_channelizer->getChannelSampleRate();
|
||||
}
|
101
plugins/channeltx/modm17/m17modbaseband.h
Normal file
101
plugins/channeltx/modm17/m17modbaseband.h
Normal file
@ -0,0 +1,101 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_M17MODBASEBAND_H
|
||||
#define INCLUDE_M17MODBASEBAND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
|
||||
#include "dsp/samplesourcefifo.h"
|
||||
#include "util/message.h"
|
||||
#include "util/messagequeue.h"
|
||||
|
||||
#include "m17modsource.h"
|
||||
|
||||
class UpChannelizer;
|
||||
class ChannelAPI;
|
||||
|
||||
class M17ModBaseband : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
class MsgConfigureM17ModBaseband : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const M17ModSettings& getSettings() const { return m_settings; }
|
||||
bool getForce() const { return m_force; }
|
||||
|
||||
static MsgConfigureM17ModBaseband* create(const M17ModSettings& settings, bool force)
|
||||
{
|
||||
return new MsgConfigureM17ModBaseband(settings, force);
|
||||
}
|
||||
|
||||
private:
|
||||
M17ModSettings m_settings;
|
||||
bool m_force;
|
||||
|
||||
MsgConfigureM17ModBaseband(const M17ModSettings& settings, bool force) :
|
||||
Message(),
|
||||
m_settings(settings),
|
||||
m_force(force)
|
||||
{ }
|
||||
};
|
||||
|
||||
M17ModBaseband();
|
||||
~M17ModBaseband();
|
||||
void reset();
|
||||
void pull(const SampleVector::iterator& begin, unsigned int nbSamples);
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
double getMagSq() const { return m_source.getMagSq(); }
|
||||
int getAudioSampleRate() const { return m_source.getAudioSampleRate(); }
|
||||
int getFeedbackAudioSampleRate() const { return m_source.getFeedbackAudioSampleRate(); }
|
||||
int getChannelSampleRate() const;
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_source.setInputFileStream(ifstream); }
|
||||
AudioFifo *getAudioFifo() { return m_source.getAudioFifo(); }
|
||||
AudioFifo *getFeedbackAudioFifo() { return m_source.getFeedbackAudioFifo(); }
|
||||
void setChannel(ChannelAPI *channel);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Level changed
|
||||
* \param rmsLevel RMS level in range 0.0 - 1.0
|
||||
* \param peakLevel Peak level in range 0.0 - 1.0
|
||||
* \param numSamples Number of audio samples analyzed
|
||||
*/
|
||||
void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples);
|
||||
|
||||
private:
|
||||
SampleSourceFifo m_sampleFifo;
|
||||
UpChannelizer *m_channelizer;
|
||||
M17ModSource m_source;
|
||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
||||
M17ModSettings m_settings;
|
||||
QMutex m_mutex;
|
||||
|
||||
void processFifo(SampleVector& data, unsigned int iBegin, unsigned int iEnd);
|
||||
bool handleMessage(const Message& cmd);
|
||||
void applySettings(const M17ModSettings& settings, bool force = false);
|
||||
|
||||
private slots:
|
||||
void handleInputMessages();
|
||||
void handleData(); //!< Handle data when samples have to be processed
|
||||
};
|
||||
|
||||
|
||||
#endif // INCLUDE_M17MODBASEBAND_H
|
599
plugins/channeltx/modm17/m17modgui.cpp
Normal file
599
plugins/channeltx/modm17/m17modgui.cpp
Normal file
@ -0,0 +1,599 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QFileDialog>
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include "device/deviceuiset.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "util/db.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "gui/crightclickenabler.h"
|
||||
#include "gui/audioselectdialog.h"
|
||||
#include "gui/basicchannelsettingsdialog.h"
|
||||
#include "gui/devicestreamselectiondialog.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "ui_m17modgui.h"
|
||||
#include "m17modgui.h"
|
||||
|
||||
|
||||
M17ModGUI* M17ModGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx)
|
||||
{
|
||||
M17ModGUI* gui = new M17ModGUI(pluginAPI, deviceUISet, channelTx);
|
||||
return gui;
|
||||
}
|
||||
|
||||
void M17ModGUI::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void M17ModGUI::resetToDefaults()
|
||||
{
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
}
|
||||
|
||||
QByteArray M17ModGUI::serialize() const
|
||||
{
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool M17ModGUI::deserialize(const QByteArray& data)
|
||||
{
|
||||
if(m_settings.deserialize(data)) {
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::resizeEvent(QResizeEvent* size)
|
||||
{
|
||||
int maxWidth = getRollupContents()->maximumWidth();
|
||||
int minHeight = getRollupContents()->minimumHeight() + getAdditionalHeight();
|
||||
resize(width() < maxWidth ? width() : maxWidth, minHeight);
|
||||
size->accept();
|
||||
}
|
||||
|
||||
bool M17ModGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (M17Mod::MsgReportFileSourceStreamData::match(message))
|
||||
{
|
||||
m_recordSampleRate = ((M17Mod::MsgReportFileSourceStreamData&)message).getSampleRate();
|
||||
m_recordLength = ((M17Mod::MsgReportFileSourceStreamData&)message).getRecordLength();
|
||||
m_samplesCount = 0;
|
||||
updateWithStreamData();
|
||||
return true;
|
||||
}
|
||||
else if (M17Mod::MsgReportFileSourceStreamTiming::match(message))
|
||||
{
|
||||
m_samplesCount = ((M17Mod::MsgReportFileSourceStreamTiming&)message).getSamplesCount();
|
||||
updateWithStreamTime();
|
||||
return true;
|
||||
}
|
||||
else if (M17Mod::MsgConfigureM17Mod::match(message))
|
||||
{
|
||||
const M17Mod::MsgConfigureM17Mod& cfg = (M17Mod::MsgConfigureM17Mod&) message;
|
||||
m_settings = cfg.getSettings();
|
||||
blockApplySettings(true);
|
||||
m_channelMarker.updateSettings(static_cast<const ChannelMarker*>(m_settings.m_channelMarker));
|
||||
displaySettings();
|
||||
blockApplySettings(false);
|
||||
return true;
|
||||
}
|
||||
else if (DSPSignalNotification::match(message))
|
||||
{
|
||||
const DSPSignalNotification& notif = (const DSPSignalNotification&) message;
|
||||
m_deviceCenterFrequency = notif.getCenterFrequency();
|
||||
m_basebandSampleRate = notif.getSampleRate();
|
||||
ui->deltaFrequency->setValueRange(false, 7, -m_basebandSampleRate/2, m_basebandSampleRate/2);
|
||||
ui->deltaFrequencyLabel->setToolTip(tr("Range %1 %L2 Hz").arg(QChar(0xB1)).arg(m_basebandSampleRate/2));
|
||||
updateAbsoluteCenterFrequency();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::channelMarkerChangedByCursor()
|
||||
{
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::handleSourceMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = getInputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::on_deltaFrequency_changed(qint64 value)
|
||||
{
|
||||
m_channelMarker.setCenterFrequency(value);
|
||||
m_settings.m_inputFrequencyOffset = m_channelMarker.getCenterFrequency();
|
||||
updateAbsoluteCenterFrequency();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_rfBW_valueChanged(int value)
|
||||
{
|
||||
ui->rfBWText->setText(QString("%1k").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_rfBandwidth = value * 100.0;
|
||||
m_channelMarker.setBandwidth(m_settings.m_rfBandwidth);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_fmDev_valueChanged(int value)
|
||||
{
|
||||
ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_fmDeviation = value * 200.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_volume_valueChanged(int value)
|
||||
{
|
||||
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
|
||||
m_settings.m_volumeFactor = value / 10.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_toneFrequency_valueChanged(int value)
|
||||
{
|
||||
ui->toneFrequencyText->setText(QString("%1k").arg(value / 100.0, 0, 'f', 2));
|
||||
m_settings.m_toneFrequency = value * 10.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_channelMute_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_channelMute = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_playLoop_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_playLoop = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_play_toggled(bool checked)
|
||||
{
|
||||
ui->tone->setEnabled(!checked); // release other source inputs
|
||||
ui->mic->setEnabled(!checked);
|
||||
m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputFile : M17ModSettings::M17ModInputNone;
|
||||
applySettings();
|
||||
ui->navTimeSlider->setEnabled(!checked);
|
||||
m_enableNavTime = !checked;
|
||||
}
|
||||
|
||||
void M17ModGUI::on_tone_toggled(bool checked)
|
||||
{
|
||||
ui->play->setEnabled(!checked); // release other source inputs
|
||||
ui->mic->setEnabled(!checked);
|
||||
m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputTone : M17ModSettings::M17ModInputNone;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_mic_toggled(bool checked)
|
||||
{
|
||||
ui->play->setEnabled(!checked); // release other source inputs
|
||||
ui->tone->setEnabled(!checked); // release other source inputs
|
||||
m_settings.m_modAFInput = checked ? M17ModSettings::M17ModInputAudio : M17ModSettings::M17ModInputNone;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_feedbackEnable_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_feedbackAudioEnable = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_feedbackVolume_valueChanged(int value)
|
||||
{
|
||||
ui->feedbackVolumeText->setText(QString("%1").arg(value / 100.0, 0, 'f', 2));
|
||||
m_settings.m_feedbackVolumeFactor = value / 100.0;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::on_navTimeSlider_valueChanged(int value)
|
||||
{
|
||||
if (m_enableNavTime && ((value >= 0) && (value <= 100)))
|
||||
{
|
||||
int t_sec = (m_recordLength * value) / 100;
|
||||
QTime t(0, 0, 0, 0);
|
||||
t = t.addSecs(t_sec);
|
||||
|
||||
M17Mod::MsgConfigureFileSourceSeek* message = M17Mod::MsgConfigureFileSourceSeek::create(value);
|
||||
m_m17Mod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::on_showFileDialog_clicked(bool checked)
|
||||
{
|
||||
(void) checked;
|
||||
QString fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open raw audio file"), ".", tr("Raw audio Files (*.raw)"), 0, QFileDialog::DontUseNativeDialog);
|
||||
|
||||
if (fileName != "")
|
||||
{
|
||||
m_fileName = fileName;
|
||||
ui->recordFileText->setText(m_fileName);
|
||||
ui->play->setEnabled(true);
|
||||
configureFileName();
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::configureFileName()
|
||||
{
|
||||
qDebug() << "M17ModGUI::configureFileName: " << m_fileName.toStdString().c_str();
|
||||
M17Mod::MsgConfigureFileSourceName* message = M17Mod::MsgConfigureFileSourceName::create(m_fileName);
|
||||
m_m17Mod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
||||
void M17ModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
{
|
||||
(void) widget;
|
||||
(void) rollDown;
|
||||
|
||||
getRollupContents()->saveState(m_rollupState);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void M17ModGUI::onMenuDialogCalled(const QPoint &p)
|
||||
{
|
||||
if (m_contextMenuType == ContextMenuChannelSettings)
|
||||
{
|
||||
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.setDefaultTitle(m_displayedName);
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
dialog.setNumberOfStreams(m_m17Mod->getNumberOfDeviceStreams());
|
||||
dialog.setStreamIndex(m_settings.m_streamIndex);
|
||||
}
|
||||
|
||||
dialog.move(p);
|
||||
dialog.exec();
|
||||
|
||||
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);
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
setTitleColor(m_settings.m_rgbColor);
|
||||
|
||||
if (m_deviceUISet->m_deviceMIMOEngine)
|
||||
{
|
||||
m_settings.m_streamIndex = dialog.getSelectedStreamIndex();
|
||||
m_channelMarker.clearStreamIndexes();
|
||||
m_channelMarker.addStreamIndex(m_settings.m_streamIndex);
|
||||
updateIndexLabel();
|
||||
}
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
||||
resetContextMenuType();
|
||||
}
|
||||
|
||||
M17ModGUI::M17ModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent) :
|
||||
ChannelGUI(parent),
|
||||
ui(new Ui::M17ModGUI),
|
||||
m_pluginAPI(pluginAPI),
|
||||
m_deviceUISet(deviceUISet),
|
||||
m_channelMarker(this),
|
||||
m_deviceCenterFrequency(0),
|
||||
m_basebandSampleRate(1),
|
||||
m_doApplySettings(true),
|
||||
m_recordLength(0),
|
||||
m_recordSampleRate(48000),
|
||||
m_samplesCount(0),
|
||||
m_audioSampleRate(-1),
|
||||
m_feedbackAudioSampleRate(-1),
|
||||
m_tickCount(0),
|
||||
m_enableNavTime(false),
|
||||
m_dcsCodeValidator(QRegExp("[0-7]{1,3}"))
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
m_helpURL = "plugins/channeltx/modm17/readme.md";
|
||||
RollupContents *rollupContents = getRollupContents();
|
||||
ui->setupUi(rollupContents);
|
||||
setSizePolicy(rollupContents->sizePolicy());
|
||||
rollupContents->arrangeRollups();
|
||||
connect(rollupContents, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
|
||||
m_m17Mod = (M17Mod*) channelTx;
|
||||
m_m17Mod->setMessageQueueToGUI(getInputMessageQueue());
|
||||
|
||||
connect(&MainCore::instance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
|
||||
|
||||
CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->mic);
|
||||
connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
|
||||
|
||||
CRightClickEnabler *feedbackRightClickEnabler = new CRightClickEnabler(ui->feedbackEnable);
|
||||
connect(feedbackRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioFeedbackSelect()));
|
||||
|
||||
ui->deltaFrequencyLabel->setText(QString("%1f").arg(QChar(0x94, 0x03)));
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
|
||||
ui->deltaFrequency->setValueRange(false, 7, -9999999, 9999999);
|
||||
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setColor(Qt::red);
|
||||
m_channelMarker.setBandwidth(12500);
|
||||
m_channelMarker.setCenterFrequency(0);
|
||||
m_channelMarker.setTitle("M17 Modulator");
|
||||
m_channelMarker.setSourceOrSinkStream(false);
|
||||
m_channelMarker.blockSignals(false);
|
||||
m_channelMarker.setVisible(true); // activate signal on the last setting only
|
||||
|
||||
m_deviceUISet->addChannelMarker(&m_channelMarker);
|
||||
|
||||
connect(&m_channelMarker, SIGNAL(changedByCursor()), this, SLOT(channelMarkerChangedByCursor()));
|
||||
|
||||
ui->play->setEnabled(false);
|
||||
ui->play->setChecked(false);
|
||||
ui->tone->setChecked(false);
|
||||
ui->mic->setChecked(false);
|
||||
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
|
||||
m_m17Mod->setLevelMeter(ui->volumeMeter);
|
||||
|
||||
m_settings.setChannelMarker(&m_channelMarker);
|
||||
m_settings.setRollupState(&m_rollupState);
|
||||
|
||||
displaySettings();
|
||||
makeUIConnections();
|
||||
applySettings();
|
||||
}
|
||||
|
||||
M17ModGUI::~M17ModGUI()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void M17ModGUI::blockApplySettings(bool block)
|
||||
{
|
||||
m_doApplySettings = !block;
|
||||
}
|
||||
|
||||
void M17ModGUI::applySettings(bool force)
|
||||
{
|
||||
if (m_doApplySettings)
|
||||
{
|
||||
M17Mod::MsgConfigureM17Mod *msg = M17Mod::MsgConfigureM17Mod::create(m_settings, force);
|
||||
m_m17Mod->getInputMessageQueue()->push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::displaySettings()
|
||||
{
|
||||
m_channelMarker.blockSignals(true);
|
||||
m_channelMarker.setCenterFrequency(m_settings.m_inputFrequencyOffset);
|
||||
m_channelMarker.setTitle(m_settings.m_title);
|
||||
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());
|
||||
setTitle(m_channelMarker.getTitle());
|
||||
updateIndexLabel();
|
||||
|
||||
blockApplySettings(true);
|
||||
|
||||
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
|
||||
|
||||
ui->rfBWText->setText(QString("%1k").arg(m_settings.m_rfBandwidth / 1000.0, 0, 'f', 1));
|
||||
ui->rfBW->setValue(m_settings.m_rfBandwidth / 100.0);
|
||||
|
||||
ui->fmDevText->setText(QString("%1%2k").arg(QChar(0xB1, 0x00)).arg(m_settings.m_fmDeviation / 2000.0, 0, 'f', 1));
|
||||
ui->fmDev->setValue(m_settings.m_fmDeviation / 200.0);
|
||||
|
||||
ui->volumeText->setText(QString("%1").arg(m_settings.m_volumeFactor, 0, 'f', 1));
|
||||
ui->volume->setValue(m_settings.m_volumeFactor * 10.0);
|
||||
|
||||
ui->toneFrequencyText->setText(QString("%1k").arg(m_settings.m_toneFrequency / 1000.0, 0, 'f', 2));
|
||||
ui->toneFrequency->setValue(m_settings.m_toneFrequency / 10.0);
|
||||
|
||||
ui->channelMute->setChecked(m_settings.m_channelMute);
|
||||
ui->playLoop->setChecked(m_settings.m_playLoop);
|
||||
|
||||
ui->tone->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputTone) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone));
|
||||
ui->mic->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputAudio) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone));
|
||||
ui->play->setEnabled((m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputFile) || (m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputNone));
|
||||
|
||||
ui->tone->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputTone);
|
||||
ui->mic->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputAudio);
|
||||
ui->play->setChecked(m_settings.m_modAFInput == M17ModSettings::M17ModInputAF::M17ModInputFile);
|
||||
|
||||
ui->feedbackEnable->setChecked(m_settings.m_feedbackAudioEnable);
|
||||
ui->feedbackVolume->setValue(roundf(m_settings.m_feedbackVolumeFactor * 100.0));
|
||||
ui->feedbackVolumeText->setText(QString("%1").arg(m_settings.m_feedbackVolumeFactor, 0, 'f', 2));
|
||||
|
||||
getRollupContents()->restoreState(m_rollupState);
|
||||
updateAbsoluteCenterFrequency();
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
void M17ModGUI::leaveEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(false);
|
||||
ChannelGUI::leaveEvent(event);
|
||||
}
|
||||
|
||||
void M17ModGUI::enterEvent(QEvent* event)
|
||||
{
|
||||
m_channelMarker.setHighlighted(true);
|
||||
ChannelGUI::enterEvent(event);
|
||||
}
|
||||
|
||||
void M17ModGUI::audioSelect()
|
||||
{
|
||||
qDebug("M17ModGUI::audioSelect");
|
||||
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName, true); // true for input
|
||||
audioSelect.exec();
|
||||
|
||||
if (audioSelect.m_selected)
|
||||
{
|
||||
m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName;
|
||||
applySettings();
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::audioFeedbackSelect()
|
||||
{
|
||||
qDebug("M17ModGUI::audioFeedbackSelect");
|
||||
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName, false); // false for output
|
||||
audioSelect.exec();
|
||||
|
||||
if (audioSelect.m_selected)
|
||||
{
|
||||
m_settings.m_feedbackAudioDeviceName = audioSelect.m_audioDeviceName;
|
||||
applySettings();
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::tick()
|
||||
{
|
||||
double powDb = CalcDb::dbPower(m_m17Mod->getMagSq());
|
||||
m_channelPowerDbAvg(powDb);
|
||||
ui->channelPower->setText(tr("%1 dB").arg(m_channelPowerDbAvg.asDouble(), 0, 'f', 1));
|
||||
|
||||
int audioSampleRate = m_m17Mod->getAudioSampleRate();
|
||||
|
||||
if (audioSampleRate != m_audioSampleRate)
|
||||
{
|
||||
if (audioSampleRate < 0) {
|
||||
ui->mic->setColor(QColor("red"));
|
||||
} else {
|
||||
ui->mic->resetColor();
|
||||
}
|
||||
|
||||
m_audioSampleRate = audioSampleRate;
|
||||
}
|
||||
|
||||
int feedbackAudioSampleRate = m_m17Mod->getFeedbackAudioSampleRate();
|
||||
|
||||
if (feedbackAudioSampleRate != m_feedbackAudioSampleRate)
|
||||
{
|
||||
if (feedbackAudioSampleRate < 0) {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background-color : red; }");
|
||||
} else {
|
||||
ui->feedbackEnable->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
m_feedbackAudioSampleRate = feedbackAudioSampleRate;
|
||||
}
|
||||
|
||||
if (((++m_tickCount & 0xf) == 0) && (m_settings.m_modAFInput == M17ModSettings::M17ModInputFile))
|
||||
{
|
||||
M17Mod::MsgConfigureFileSourceStreamTiming* message = M17Mod::MsgConfigureFileSourceStreamTiming::create();
|
||||
m_m17Mod->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::updateWithStreamData()
|
||||
{
|
||||
QTime recordLength(0, 0, 0, 0);
|
||||
recordLength = recordLength.addSecs(m_recordLength);
|
||||
QString s_time = recordLength.toString("HH:mm:ss");
|
||||
ui->recordLengthText->setText(s_time);
|
||||
updateWithStreamTime();
|
||||
}
|
||||
|
||||
void M17ModGUI::updateWithStreamTime()
|
||||
{
|
||||
int t_sec = 0;
|
||||
int t_msec = 0;
|
||||
|
||||
if (m_recordSampleRate > 0)
|
||||
{
|
||||
t_msec = ((m_samplesCount * 1000) / m_recordSampleRate) % 1000;
|
||||
t_sec = m_samplesCount / m_recordSampleRate;
|
||||
}
|
||||
|
||||
QTime t(0, 0, 0, 0);
|
||||
t = t.addSecs(t_sec);
|
||||
t = t.addMSecs(t_msec);
|
||||
QString s_timems = t.toString("HH:mm:ss.zzz");
|
||||
QString s_time = t.toString("HH:mm:ss");
|
||||
ui->relTimeText->setText(s_timems);
|
||||
|
||||
if (!m_enableNavTime)
|
||||
{
|
||||
float posRatio = (float) t_sec / (float) m_recordLength;
|
||||
ui->navTimeSlider->setValue((int) (posRatio * 100.0));
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModGUI::makeUIConnections()
|
||||
{
|
||||
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &M17ModGUI::on_deltaFrequency_changed);
|
||||
QObject::connect(ui->rfBW, &QSlider::valueChanged, this, &M17ModGUI::on_rfBW_valueChanged);
|
||||
QObject::connect(ui->fmDev, &QSlider::valueChanged, this, &M17ModGUI::on_fmDev_valueChanged);
|
||||
QObject::connect(ui->toneFrequency, &QDial::valueChanged, this, &M17ModGUI::on_toneFrequency_valueChanged);
|
||||
QObject::connect(ui->volume, &QDial::valueChanged, this, &M17ModGUI::on_volume_valueChanged);
|
||||
QObject::connect(ui->channelMute, &QToolButton::toggled, this, &M17ModGUI::on_channelMute_toggled);
|
||||
QObject::connect(ui->tone, &ButtonSwitch::toggled, this, &M17ModGUI::on_tone_toggled);
|
||||
QObject::connect(ui->mic, &ButtonSwitch::toggled, this, &M17ModGUI::on_mic_toggled);
|
||||
QObject::connect(ui->play, &ButtonSwitch::toggled, this, &M17ModGUI::on_play_toggled);
|
||||
QObject::connect(ui->playLoop, &ButtonSwitch::toggled, this, &M17ModGUI::on_playLoop_toggled);
|
||||
QObject::connect(ui->navTimeSlider, &QSlider::valueChanged, this, &M17ModGUI::on_navTimeSlider_valueChanged);
|
||||
QObject::connect(ui->showFileDialog, &QPushButton::clicked, this, &M17ModGUI::on_showFileDialog_clicked);
|
||||
QObject::connect(ui->feedbackEnable, &QToolButton::toggled, this, &M17ModGUI::on_feedbackEnable_toggled);
|
||||
QObject::connect(ui->feedbackVolume, &QDial::valueChanged, this, &M17ModGUI::on_feedbackVolume_valueChanged);
|
||||
}
|
||||
|
||||
void M17ModGUI::updateAbsoluteCenterFrequency()
|
||||
{
|
||||
setStatusFrequency(m_deviceCenterFrequency + m_settings.m_inputFrequencyOffset);
|
||||
}
|
140
plugins/channeltx/modm17/m17modgui.h
Normal file
140
plugins/channeltx/modm17/m17modgui.h
Normal file
@ -0,0 +1,140 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_CHANNELTX_MODM17_M17MODGUI_H_
|
||||
#define PLUGINS_CHANNELTX_MODM17_M17MODGUI_H_
|
||||
|
||||
#include <QRegExpValidator>
|
||||
|
||||
#include "channel/channelgui.h"
|
||||
#include "dsp/channelmarker.h"
|
||||
#include "util/movingaverage.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "settings/rollupstate.h"
|
||||
|
||||
#include "m17mod.h"
|
||||
#include "m17modsettings.h"
|
||||
|
||||
class PluginAPI;
|
||||
class DeviceUISet;
|
||||
class BasebandSampleSource;
|
||||
|
||||
namespace Ui {
|
||||
class M17ModGUI;
|
||||
}
|
||||
|
||||
class M17ModGUI : public ChannelGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static M17ModGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx);
|
||||
virtual void destroy();
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
virtual void setWorkspaceIndex(int index) { m_settings.m_workspaceIndex = index; };
|
||||
virtual int getWorkspaceIndex() const { return m_settings.m_workspaceIndex; };
|
||||
virtual void setGeometryBytes(const QByteArray& blob) { m_settings.m_geometryBytes = blob; };
|
||||
virtual QByteArray getGeometryBytes() const { return m_settings.m_geometryBytes; };
|
||||
virtual QString getTitle() const { return m_settings.m_title; };
|
||||
virtual QColor getTitleColor() const { return m_settings.m_rgbColor; };
|
||||
virtual void zetHidden(bool hidden) { m_settings.m_hidden = hidden; }
|
||||
virtual bool getHidden() const { return m_settings.m_hidden; }
|
||||
virtual ChannelMarker& getChannelMarker() { return m_channelMarker; }
|
||||
virtual int getStreamIndex() const { return m_settings.m_streamIndex; }
|
||||
virtual void setStreamIndex(int streamIndex) { m_settings.m_streamIndex = streamIndex; }
|
||||
|
||||
public slots:
|
||||
void channelMarkerChangedByCursor();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* size);
|
||||
|
||||
private:
|
||||
Ui::M17ModGUI* ui;
|
||||
PluginAPI* m_pluginAPI;
|
||||
DeviceUISet* m_deviceUISet;
|
||||
ChannelMarker m_channelMarker;
|
||||
RollupState m_rollupState;
|
||||
M17ModSettings m_settings;
|
||||
qint64 m_deviceCenterFrequency;
|
||||
int m_basebandSampleRate;
|
||||
bool m_doApplySettings;
|
||||
|
||||
M17Mod* m_m17Mod;
|
||||
MovingAverageUtil<double, double, 20> m_channelPowerDbAvg;
|
||||
|
||||
QString m_fileName;
|
||||
quint32 m_recordLength;
|
||||
int m_recordSampleRate;
|
||||
int m_samplesCount;
|
||||
int m_audioSampleRate;
|
||||
int m_feedbackAudioSampleRate;
|
||||
std::size_t m_tickCount;
|
||||
bool m_enableNavTime;
|
||||
M17ModSettings::M17ModInputAF m_modAFInput;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
QRegExpValidator m_dcsCodeValidator;
|
||||
|
||||
explicit M17ModGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx, QWidget* parent = nullptr);
|
||||
virtual ~M17ModGUI();
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void updateWithStreamData();
|
||||
void updateWithStreamTime();
|
||||
bool handleMessage(const Message& message);
|
||||
void makeUIConnections();
|
||||
void updateAbsoluteCenterFrequency();
|
||||
|
||||
void leaveEvent(QEvent*);
|
||||
void enterEvent(QEvent*);
|
||||
|
||||
private slots:
|
||||
void handleSourceMessages();
|
||||
|
||||
void on_deltaFrequency_changed(qint64 value);
|
||||
void on_channelSpacingApply_clicked();
|
||||
void on_rfBW_valueChanged(int value);
|
||||
void on_fmDev_valueChanged(int value);
|
||||
void on_toneFrequency_valueChanged(int value);
|
||||
void on_volume_valueChanged(int value);
|
||||
void on_channelMute_toggled(bool checked);
|
||||
void on_tone_toggled(bool checked);
|
||||
void on_mic_toggled(bool checked);
|
||||
void on_play_toggled(bool checked);
|
||||
|
||||
void on_playLoop_toggled(bool checked);
|
||||
void on_navTimeSlider_valueChanged(int value);
|
||||
void on_showFileDialog_clicked(bool checked);
|
||||
|
||||
void on_feedbackEnable_toggled(bool checked);
|
||||
void on_feedbackVolume_valueChanged(int value);
|
||||
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
|
||||
void configureFileName();
|
||||
void audioSelect();
|
||||
void audioFeedbackSelect();
|
||||
void tick();
|
||||
};
|
||||
|
||||
#endif /* PLUGINS_CHANNELTX_MODM17_M17MODGUI_H_ */
|
737
plugins/channeltx/modm17/m17modgui.ui
Normal file
737
plugins/channeltx/modm17/m17modgui.ui
Normal file
@ -0,0 +1,737 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>M17ModGUI</class>
|
||||
<widget class="RollupContents" name="M17ModGUI">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>360</width>
|
||||
<height>278</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>360</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>560</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>9</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>M17 Modulator</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="settingsContainer" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>358</width>
|
||||
<height>271</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>358</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<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>32</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>
|
||||
<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="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>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="channelMute">
|
||||
<property name="toolTip">
|
||||
<string>Mute/Unmute channel</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/txon.png</normaloff>
|
||||
<normalon>:/txoff.png</normalon>:/txon.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="fmDeviationLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="rfBWLabel">
|
||||
<property name="text">
|
||||
<string>RFBW</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="rfBW">
|
||||
<property name="toolTip">
|
||||
<string>RF bandwidth (kHz)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>480</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>160</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rfBWText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>25.0k</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fmDevLabel">
|
||||
<property name="text">
|
||||
<string>Dev</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="fmDev">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>FM peak deviation (kHz)</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fmDevText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+20.0k</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="volumeLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="volLabel">
|
||||
<property name="text">
|
||||
<string>Vol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="volume">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio input gain</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="volumeText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>25</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio input gain value</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1.0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LevelMeterVU" name="volumeMeter" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Mono</family>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Level (% full range) top trace: average, bottom trace: instantaneous peak, tip: peak hold</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="recordFileSelectLayout">
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="tone">
|
||||
<property name="toolTip">
|
||||
<string>Tone modulation (1 kHz)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/carrier.png</normaloff>:/carrier.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="toneFrequency">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Tone frequency</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>250</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="toneFrequencyText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>36</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Tone frequency (kHz)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1.00k</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="mic">
|
||||
<property name="toolTip">
|
||||
<string>Audio input</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/microphone.png</normaloff>:/microphone.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="feedbackEnable">
|
||||
<property name="toolTip">
|
||||
<string>Left: enable / disable audio feedback - Right: select audio output device</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/sound_off.png</normaloff>
|
||||
<normalon>:/sound_on.png</normalon>:/sound_off.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="feedbackVolume">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio feedback volume</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="feedbackVolumeText">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio feedback volume</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1.00</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<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="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="fileNameLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="recordFileText">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="playControllLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="showFileDialog">
|
||||
<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="toolTip">
|
||||
<string>Open record file (48 kHz 32 bit float LE mono)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/preset-load.png</normaloff>:/preset-load.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="playLoop">
|
||||
<property name="toolTip">
|
||||
<string>Play record file in a loop</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/playloop.png</normaloff>:/playloop.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="play">
|
||||
<property name="toolTip">
|
||||
<string>Record file play/pause</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/play.png</normaloff>
|
||||
<normalon>:/pause.png</normalon>
|
||||
<disabledoff>:/play.png</disabledoff>
|
||||
<disabledon>:/play.png</disabledon>:/play.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<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="Line" name="linePlay1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="relTimeText">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>90</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Record time from start</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>00:00:00.000</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="linePlay2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="recordLengthText">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Total record time</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>00:00:00</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_nav">
|
||||
<item>
|
||||
<widget class="QSlider" name="navTimeSlider">
|
||||
<property name="toolTip">
|
||||
<string>Record file time navigator</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RollupContents</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/rollupcontents.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>LevelMeterVU</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/levelmeter.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
92
plugins/channeltx/modm17/m17modplugin.cpp
Normal file
92
plugins/channeltx/modm17/m17modplugin.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 "plugin/pluginapi.h"
|
||||
|
||||
#ifndef SERVER_MODE
|
||||
#include "m17modgui.h"
|
||||
#endif
|
||||
#include "m17mod.h"
|
||||
#include "m17modwebapiadapter.h"
|
||||
#include "m17modplugin.h"
|
||||
|
||||
const PluginDescriptor M17ModPlugin::m_pluginDescriptor = {
|
||||
M17Mod::m_channelId,
|
||||
QStringLiteral("M17 Modulator"),
|
||||
QStringLiteral("7.4.0"),
|
||||
QStringLiteral("(c) Edouard Griffiths, F4EXB"),
|
||||
QStringLiteral("https://github.com/f4exb/sdrangel"),
|
||||
true,
|
||||
QStringLiteral("https://github.com/f4exb/sdrangel")
|
||||
};
|
||||
|
||||
M17ModPlugin::M17ModPlugin(QObject* parent) :
|
||||
QObject(parent),
|
||||
m_pluginAPI(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
const PluginDescriptor& M17ModPlugin::getPluginDescriptor() const
|
||||
{
|
||||
return m_pluginDescriptor;
|
||||
}
|
||||
|
||||
void M17ModPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
{
|
||||
m_pluginAPI = pluginAPI;
|
||||
|
||||
// register AM modulator
|
||||
m_pluginAPI->registerTxChannel(M17Mod::m_channelIdURI, M17Mod::m_channelId, this);
|
||||
}
|
||||
|
||||
void M17ModPlugin::createTxChannel(DeviceAPI *deviceAPI, BasebandSampleSource **bs, ChannelAPI **cs) const
|
||||
{
|
||||
if (bs || cs)
|
||||
{
|
||||
M17Mod *instance = new M17Mod(deviceAPI);
|
||||
|
||||
if (bs) {
|
||||
*bs = instance;
|
||||
}
|
||||
|
||||
if (cs) {
|
||||
*cs = instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERVER_MODE
|
||||
ChannelGUI* M17ModPlugin::createTxChannelGUI(
|
||||
DeviceUISet *deviceUISet,
|
||||
BasebandSampleSource *txChannel) const
|
||||
{
|
||||
(void) deviceUISet;
|
||||
(void) txChannel;
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
ChannelGUI* M17ModPlugin::createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel) const
|
||||
{
|
||||
return M17ModGUI::create(m_pluginAPI, deviceUISet, txChannel);
|
||||
}
|
||||
#endif
|
||||
|
||||
ChannelWebAPIAdapter* M17ModPlugin::createChannelWebAPIAdapter() const
|
||||
{
|
||||
return new M17ModWebAPIAdapter();
|
||||
}
|
48
plugins/channeltx/modm17/m17modplugin.h
Normal file
48
plugins/channeltx/modm17/m17modplugin.h
Normal file
@ -0,0 +1,48 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_M17MODPLUGIN_H
|
||||
#define INCLUDE_M17MODPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include "plugin/plugininterface.h"
|
||||
|
||||
class DeviceUISet;
|
||||
class BasebandSampleSource;
|
||||
|
||||
class M17ModPlugin : public QObject, PluginInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(PluginInterface)
|
||||
Q_PLUGIN_METADATA(IID "sdrangel.channeltx.modm17")
|
||||
|
||||
public:
|
||||
explicit M17ModPlugin(QObject* parent = nullptr);
|
||||
|
||||
const PluginDescriptor& getPluginDescriptor() const;
|
||||
void initPlugin(PluginAPI* pluginAPI);
|
||||
|
||||
virtual void createTxChannel(DeviceAPI *deviceAPI, BasebandSampleSource **bs, ChannelAPI **cs) const;
|
||||
virtual ChannelGUI* createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *rxChannel) const;
|
||||
virtual ChannelWebAPIAdapter* createChannelWebAPIAdapter() const;
|
||||
|
||||
private:
|
||||
static const PluginDescriptor m_pluginDescriptor;
|
||||
|
||||
PluginAPI* m_pluginAPI;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_M17MODPLUGIN_H
|
179
plugins/channeltx/modm17/m17modsettings.cpp
Normal file
179
plugins/channeltx/modm17/m17modsettings.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 <QDebug>
|
||||
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/ctcssfrequencies.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "settings/serializable.h"
|
||||
#include "m17modsettings.h"
|
||||
|
||||
M17ModSettings::M17ModSettings() :
|
||||
m_channelMarker(nullptr),
|
||||
m_rollupState(nullptr)
|
||||
{
|
||||
resetToDefaults();
|
||||
}
|
||||
|
||||
void M17ModSettings::resetToDefaults()
|
||||
{
|
||||
m_inputFrequencyOffset = 0;
|
||||
m_rfBandwidth = 16000.0f;
|
||||
m_fmDeviation = 10000.0f; //!< full deviation
|
||||
m_toneFrequency = 1000.0f;
|
||||
m_volumeFactor = 1.0f;
|
||||
m_channelMute = false;
|
||||
m_playLoop = false;
|
||||
m_rgbColor = QColor(255, 0, 255).rgb();
|
||||
m_title = "M17 Modulator";
|
||||
m_modAFInput = M17ModInputAF::M17ModInputNone;
|
||||
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
m_feedbackAudioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
m_feedbackVolumeFactor = 0.5f;
|
||||
m_feedbackAudioEnable = false;
|
||||
m_streamIndex = 0;
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIDeviceIndex = 0;
|
||||
m_reverseAPIChannelIndex = 0;
|
||||
m_workspaceIndex = 0;
|
||||
m_hidden = false;
|
||||
}
|
||||
|
||||
QByteArray M17ModSettings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
|
||||
s.writeS32(1, m_inputFrequencyOffset);
|
||||
s.writeReal(2, m_rfBandwidth);
|
||||
s.writeReal(4, m_fmDeviation);
|
||||
s.writeU32(5, m_rgbColor);
|
||||
s.writeReal(6, m_toneFrequency);
|
||||
s.writeReal(7, m_volumeFactor);
|
||||
|
||||
if (m_channelMarker) {
|
||||
s.writeBlob(11, m_channelMarker->serialize());
|
||||
}
|
||||
|
||||
s.writeString(12, m_title);
|
||||
s.writeS32(13, (int) m_modAFInput);
|
||||
s.writeString(14, m_audioDeviceName);
|
||||
s.writeBool(15, m_useReverseAPI);
|
||||
s.writeString(16, m_reverseAPIAddress);
|
||||
s.writeU32(17, m_reverseAPIPort);
|
||||
s.writeU32(18, m_reverseAPIDeviceIndex);
|
||||
s.writeU32(19, m_reverseAPIChannelIndex);
|
||||
s.writeString(20, m_feedbackAudioDeviceName);
|
||||
s.writeReal(21, m_feedbackVolumeFactor);
|
||||
s.writeBool(22, m_feedbackAudioEnable);
|
||||
s.writeS32(23, m_streamIndex);
|
||||
|
||||
if (m_rollupState) {
|
||||
s.writeBlob(27, m_rollupState->serialize());
|
||||
}
|
||||
|
||||
s.writeS32(28, m_workspaceIndex);
|
||||
s.writeBlob(29, m_geometryBytes);
|
||||
s.writeBool(30, m_hidden);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool M17ModSettings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
qint32 tmp;
|
||||
uint32_t utmp;
|
||||
|
||||
d.readS32(1, &tmp, 0);
|
||||
m_inputFrequencyOffset = tmp;
|
||||
d.readReal(2, &m_rfBandwidth, 12500.0);
|
||||
d.readReal(4, &m_fmDeviation, 10000.0);
|
||||
d.readU32(5, &m_rgbColor);
|
||||
d.readReal(6, &m_toneFrequency, 1000.0);
|
||||
d.readReal(7, &m_volumeFactor, 1.0);
|
||||
d.readBlob(8, &bytetmp);
|
||||
|
||||
if (m_channelMarker)
|
||||
{
|
||||
d.readBlob(11, &bytetmp);
|
||||
m_channelMarker->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readString(12, &m_title, "M17 Modulator");
|
||||
|
||||
d.readS32(13, &tmp, 0);
|
||||
if ((tmp < 0) || (tmp > (int) M17ModInputAF::M17ModInputTone)) {
|
||||
m_modAFInput = M17ModInputNone;
|
||||
} else {
|
||||
m_modAFInput = (M17ModInputAF) tmp;
|
||||
}
|
||||
|
||||
d.readString(14, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||
d.readBool(15, &m_useReverseAPI, false);
|
||||
d.readString(16, &m_reverseAPIAddress, "127.0.0.1");
|
||||
d.readU32(17, &utmp, 0);
|
||||
|
||||
if ((utmp > 1023) && (utmp < 65535)) {
|
||||
m_reverseAPIPort = utmp;
|
||||
} else {
|
||||
m_reverseAPIPort = 8888;
|
||||
}
|
||||
|
||||
d.readU32(18, &utmp, 0);
|
||||
m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readU32(19, &utmp, 0);
|
||||
m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readString(20, &m_feedbackAudioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||
d.readReal(21, &m_feedbackVolumeFactor, 1.0);
|
||||
d.readBool(22, &m_feedbackAudioEnable, false);
|
||||
d.readS32(23, &m_streamIndex, 0);
|
||||
d.readS32(25, &tmp, 0023);
|
||||
|
||||
if (m_rollupState)
|
||||
{
|
||||
d.readBlob(27, &bytetmp);
|
||||
m_rollupState->deserialize(bytetmp);
|
||||
}
|
||||
|
||||
d.readS32(28, &m_workspaceIndex, 0);
|
||||
d.readBlob(29, &m_geometryBytes);
|
||||
d.readBool(30, &m_hidden, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "NFMModSettings::deserialize: ERROR";
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
74
plugins/channeltx/modm17/m17modsettings.h
Normal file
74
plugins/channeltx/modm17/m17modsettings.h
Normal file
@ -0,0 +1,74 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_CHANNELTX_MODM17_M17MODSETTINGS_H_
|
||||
#define PLUGINS_CHANNELTX_MODM17_M17MODSETTINGS_H_
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "dsp/cwkeyersettings.h"
|
||||
|
||||
class Serializable;
|
||||
|
||||
struct M17ModSettings
|
||||
{
|
||||
enum M17ModInputAF
|
||||
{
|
||||
M17ModInputNone,
|
||||
M17ModInputFile,
|
||||
M17ModInputAudio,
|
||||
M17ModInputTone
|
||||
};
|
||||
|
||||
qint64 m_inputFrequencyOffset;
|
||||
float m_rfBandwidth;
|
||||
float m_fmDeviation;
|
||||
float m_toneFrequency;
|
||||
float m_volumeFactor;
|
||||
bool m_channelMute;
|
||||
bool m_playLoop;
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
M17ModInputAF m_modAFInput;
|
||||
QString m_audioDeviceName; //!< This is the audio device you get the audio samples from
|
||||
QString m_feedbackAudioDeviceName; //!< This is the audio device you send the audio samples to for audio feedback
|
||||
float m_feedbackVolumeFactor;
|
||||
bool m_feedbackAudioEnable;
|
||||
int m_streamIndex;
|
||||
bool m_useReverseAPI;
|
||||
QString m_reverseAPIAddress;
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
int m_workspaceIndex;
|
||||
QByteArray m_geometryBytes;
|
||||
bool m_hidden;
|
||||
|
||||
Serializable *m_channelMarker;
|
||||
Serializable *m_rollupState;
|
||||
|
||||
M17ModSettings();
|
||||
void resetToDefaults();
|
||||
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
|
||||
void setRollupState(Serializable *rollupState) { m_rollupState = rollupState; }
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* PLUGINS_CHANNELTX_MODM17_M17MODSETTINGS_H_ */
|
418
plugins/channeltx/modm17/m17modsource.cpp
Normal file
418
plugins/channeltx/modm17/m17modsource.cpp
Normal file
@ -0,0 +1,418 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 <QDebug>
|
||||
|
||||
#include "dsp/datafifo.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "m17modsource.h"
|
||||
|
||||
const int M17ModSource::m_levelNbSamples = 480; // every 10ms
|
||||
|
||||
M17ModSource::M17ModSource() :
|
||||
m_channelSampleRate(48000),
|
||||
m_channelFrequencyOffset(0),
|
||||
m_modPhasor(0.0f),
|
||||
m_audioSampleRate(48000),
|
||||
m_audioFifo(12000),
|
||||
m_feedbackAudioFifo(48000),
|
||||
m_levelCalcCount(0),
|
||||
m_peakLevel(0.0f),
|
||||
m_levelSum(0.0f),
|
||||
m_ifstream(nullptr),
|
||||
m_mutex(QMutex::Recursive)
|
||||
{
|
||||
m_audioFifo.setLabel("M17ModSource.m_audioFifo");
|
||||
m_feedbackAudioFifo.setLabel("M17ModSource.m_feedbackAudioFifo");
|
||||
m_audioBuffer.resize(24000);
|
||||
m_audioBufferFill = 0;
|
||||
m_audioReadBuffer.resize(24000);
|
||||
m_audioReadBufferFill = 0;
|
||||
|
||||
m_feedbackAudioBuffer.resize(1<<14);
|
||||
m_feedbackAudioBufferFill = 0;
|
||||
|
||||
m_demodBuffer.resize(1<<12);
|
||||
m_demodBufferFill = 0;
|
||||
|
||||
m_magsq = 0.0;
|
||||
|
||||
applySettings(m_settings, true);
|
||||
applyChannelSettings(m_channelSampleRate, m_channelFrequencyOffset, true);
|
||||
}
|
||||
|
||||
M17ModSource::~M17ModSource()
|
||||
{
|
||||
}
|
||||
|
||||
void M17ModSource::pull(SampleVector::iterator begin, unsigned int nbSamples)
|
||||
{
|
||||
std::for_each(
|
||||
begin,
|
||||
begin + nbSamples,
|
||||
[this](Sample& s) {
|
||||
pullOne(s);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void M17ModSource::pullOne(Sample& sample)
|
||||
{
|
||||
if (m_settings.m_channelMute)
|
||||
{
|
||||
sample.m_real = 0.0f;
|
||||
sample.m_imag = 0.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
Complex ci;
|
||||
|
||||
if (m_interpolatorDistance > 1.0f) // decimate
|
||||
{
|
||||
modulateSample();
|
||||
|
||||
while (!m_interpolator.decimate(&m_interpolatorDistanceRemain, m_modSample, &ci))
|
||||
{
|
||||
modulateSample();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, m_modSample, &ci))
|
||||
{
|
||||
modulateSample();
|
||||
}
|
||||
}
|
||||
|
||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||
|
||||
ci *= m_carrierNco.nextIQ(); // shift to carrier frequency
|
||||
|
||||
double magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
|
||||
magsq /= (SDR_TX_SCALED*SDR_TX_SCALED);
|
||||
m_movingAverage(magsq);
|
||||
m_magsq = m_movingAverage.asDouble();
|
||||
|
||||
sample.m_real = (FixReal) ci.real();
|
||||
sample.m_imag = (FixReal) ci.imag();
|
||||
}
|
||||
|
||||
void M17ModSource::prefetch(unsigned int nbSamples)
|
||||
{
|
||||
unsigned int nbSamplesAudio = nbSamples * ((Real) m_audioSampleRate / (Real) m_channelSampleRate);
|
||||
pullAudio(nbSamplesAudio);
|
||||
}
|
||||
|
||||
void M17ModSource::pullAudio(unsigned int nbSamplesAudio)
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
|
||||
if (nbSamplesAudio > m_audioBuffer.size()) {
|
||||
m_audioBuffer.resize(nbSamplesAudio);
|
||||
}
|
||||
|
||||
std::copy(&m_audioReadBuffer[0], &m_audioReadBuffer[nbSamplesAudio], &m_audioBuffer[0]);
|
||||
m_audioBufferFill = 0;
|
||||
|
||||
if (m_audioReadBufferFill > nbSamplesAudio) // copy back remaining samples at the start of the read buffer
|
||||
{
|
||||
std::copy(&m_audioReadBuffer[nbSamplesAudio], &m_audioReadBuffer[m_audioReadBufferFill], &m_audioReadBuffer[0]);
|
||||
m_audioReadBufferFill = m_audioReadBufferFill - nbSamplesAudio; // adjust current read buffer fill pointer
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::modulateSample()
|
||||
{
|
||||
Real t1, t;
|
||||
|
||||
pullAF(t);
|
||||
|
||||
if (m_settings.m_feedbackAudioEnable) {
|
||||
pushFeedback(t * m_settings.m_feedbackVolumeFactor * 16384.0f);
|
||||
}
|
||||
|
||||
calculateLevel(t);
|
||||
t1 = m_lowpass.filter(t) * 1.2f;
|
||||
|
||||
m_modPhasor += (m_settings.m_fmDeviation / (float) m_audioSampleRate) * t1;
|
||||
|
||||
// limit phasor range to ]-pi,pi]
|
||||
if (m_modPhasor > M_PI) {
|
||||
m_modPhasor -= (2.0f * M_PI);
|
||||
}
|
||||
|
||||
m_modSample.real(cos(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF); // -1 dB
|
||||
m_modSample.imag(sin(m_modPhasor) * 0.891235351562f * SDR_TX_SCALEF);
|
||||
|
||||
m_demodBuffer[m_demodBufferFill] = t1 * std::numeric_limits<int16_t>::max();
|
||||
++m_demodBufferFill;
|
||||
|
||||
if (m_demodBufferFill >= m_demodBuffer.size())
|
||||
{
|
||||
QList<ObjectPipe*> dataPipes;
|
||||
MainCore::instance()->getDataPipes().getDataPipes(m_channel, "demod", dataPipes);
|
||||
|
||||
if (dataPipes.size() > 0)
|
||||
{
|
||||
QList<ObjectPipe*>::iterator it = dataPipes.begin();
|
||||
|
||||
for (; it != dataPipes.end(); ++it)
|
||||
{
|
||||
DataFifo *fifo = qobject_cast<DataFifo*>((*it)->m_element);
|
||||
|
||||
if (fifo) {
|
||||
fifo->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_demodBufferFill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::pullAF(Real& sample)
|
||||
{
|
||||
switch (m_settings.m_modAFInput)
|
||||
{
|
||||
case M17ModSettings::M17ModInputTone:
|
||||
sample = m_toneNco.next();
|
||||
break;
|
||||
case M17ModSettings::M17ModInputFile:
|
||||
// sox f4exb_call.wav --encoding float --endian little f4exb_call.raw
|
||||
// ffplay -f f32le -ar 48k -ac 1 f4exb_call.raw
|
||||
if (m_ifstream && m_ifstream->is_open())
|
||||
{
|
||||
if (m_ifstream->eof())
|
||||
{
|
||||
if (m_settings.m_playLoop)
|
||||
{
|
||||
m_ifstream->clear();
|
||||
m_ifstream->seekg(0, std::ios::beg);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ifstream->eof())
|
||||
{
|
||||
sample = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ifstream->read(reinterpret_cast<char*>(&sample), sizeof(Real));
|
||||
sample *= m_settings.m_volumeFactor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sample = 0.0f;
|
||||
}
|
||||
break;
|
||||
case M17ModSettings::M17ModInputAudio:
|
||||
if (m_audioBufferFill < m_audioBuffer.size())
|
||||
{
|
||||
sample = ((m_audioBuffer[m_audioBufferFill].l + m_audioBuffer[m_audioBufferFill].r) / 65536.0f) * m_settings.m_volumeFactor;
|
||||
m_audioBufferFill++;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int size = m_audioBuffer.size();
|
||||
qDebug("NFMModSource::pullAF: starve audio samples: size: %u", size);
|
||||
sample = ((m_audioBuffer[size-1].l + m_audioBuffer[size-1].r) / 65536.0f) * m_settings.m_volumeFactor;
|
||||
}
|
||||
|
||||
break;
|
||||
case M17ModSettings::M17ModInputNone:
|
||||
default:
|
||||
sample = 0.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::pushFeedback(Real sample)
|
||||
{
|
||||
Complex c(sample, sample);
|
||||
Complex ci;
|
||||
|
||||
if (m_feedbackInterpolatorDistance < 1.0f) // interpolate
|
||||
{
|
||||
while (!m_feedbackInterpolator.interpolate(&m_feedbackInterpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
processOneSample(ci);
|
||||
m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance;
|
||||
}
|
||||
}
|
||||
else // decimate
|
||||
{
|
||||
if (m_feedbackInterpolator.decimate(&m_feedbackInterpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
processOneSample(ci);
|
||||
m_feedbackInterpolatorDistanceRemain += m_feedbackInterpolatorDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::processOneSample(Complex& ci)
|
||||
{
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].l = ci.real();
|
||||
m_feedbackAudioBuffer[m_feedbackAudioBufferFill].r = ci.imag();
|
||||
++m_feedbackAudioBufferFill;
|
||||
|
||||
if (m_feedbackAudioBufferFill >= m_feedbackAudioBuffer.size())
|
||||
{
|
||||
uint res = m_feedbackAudioFifo.write((const quint8*)&m_feedbackAudioBuffer[0], m_feedbackAudioBufferFill);
|
||||
|
||||
if (res != m_feedbackAudioBufferFill)
|
||||
{
|
||||
qDebug("M17ModSource::pushFeedback: %u/%u audio samples written m_feedbackInterpolatorDistance: %f",
|
||||
res, m_feedbackAudioBufferFill, m_feedbackInterpolatorDistance);
|
||||
m_feedbackAudioFifo.clear();
|
||||
}
|
||||
|
||||
m_feedbackAudioBufferFill = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::calculateLevel(Real& sample)
|
||||
{
|
||||
if (m_levelCalcCount < m_levelNbSamples)
|
||||
{
|
||||
m_peakLevel = std::max(std::fabs(m_peakLevel), sample);
|
||||
m_levelSum += sample * sample;
|
||||
m_levelCalcCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rmsLevel = sqrt(m_levelSum / m_levelNbSamples);
|
||||
m_peakLevelOut = m_peakLevel;
|
||||
m_peakLevel = 0.0f;
|
||||
m_levelSum = 0.0f;
|
||||
m_levelCalcCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::applyAudioSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("M17ModSource::applyAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("M17ModSource::applyAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorConsumed = false;
|
||||
m_interpolatorDistance = (Real) sampleRate / (Real) m_channelSampleRate;
|
||||
m_interpolator.create(48, sampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
|
||||
m_lowpass.create(301, sampleRate, m_settings.m_rfBandwidth);
|
||||
m_toneNco.setFreq(m_settings.m_toneFrequency, sampleRate);
|
||||
m_audioSampleRate = sampleRate;
|
||||
applyFeedbackAudioSampleRate(m_feedbackAudioSampleRate);
|
||||
|
||||
QList<ObjectPipe*> pipes;
|
||||
MainCore::instance()->getMessagePipes().getMessagePipes(m_channel, "reportdemod", pipes);
|
||||
|
||||
if (pipes.size() > 0)
|
||||
{
|
||||
for (const auto& pipe : pipes)
|
||||
{
|
||||
MessageQueue* messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
|
||||
MainCore::MsgChannelDemodReport *msg = MainCore::MsgChannelDemodReport::create(m_channel, sampleRate);
|
||||
messageQueue->push(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void M17ModSource::applyFeedbackAudioSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate < 0)
|
||||
{
|
||||
qWarning("NFMModSource::applyFeedbackAudioSampleRate: invalid sample rate %d", sampleRate);
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug("NFMModSource::applyFeedbackAudioSampleRate: %d", sampleRate);
|
||||
|
||||
m_feedbackInterpolatorDistanceRemain = 0;
|
||||
m_feedbackInterpolatorConsumed = false;
|
||||
m_feedbackInterpolatorDistance = (Real) sampleRate / (Real) m_audioSampleRate;
|
||||
Real cutoff = std::min(sampleRate, m_audioSampleRate) / 2.2f;
|
||||
m_feedbackInterpolator.create(48, sampleRate, cutoff, 3.0);
|
||||
m_feedbackAudioSampleRate = sampleRate;
|
||||
}
|
||||
|
||||
void M17ModSource::applySettings(const M17ModSettings& settings, bool force)
|
||||
{
|
||||
if ((settings.m_rfBandwidth != m_settings.m_rfBandwidth) || force)
|
||||
{
|
||||
m_settings.m_rfBandwidth = settings.m_rfBandwidth;
|
||||
applyAudioSampleRate(m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_toneFrequency != m_settings.m_toneFrequency) || force) {
|
||||
m_toneNco.setFreq(settings.m_toneFrequency, m_audioSampleRate);
|
||||
}
|
||||
|
||||
if ((settings.m_modAFInput != m_settings.m_modAFInput) || force)
|
||||
{
|
||||
if (settings.m_modAFInput == M17ModSettings::M17ModInputAudio) {
|
||||
connect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
|
||||
} else {
|
||||
disconnect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
|
||||
}
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
void M17ModSource::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
|
||||
{
|
||||
qDebug() << "M17ModSource::applyChannelSettings:"
|
||||
<< " channelSampleRate: " << channelSampleRate
|
||||
<< " channelFrequencyOffset: " << channelFrequencyOffset;
|
||||
|
||||
if ((channelFrequencyOffset != m_channelFrequencyOffset)
|
||||
|| (channelSampleRate != m_channelSampleRate) || force)
|
||||
{
|
||||
m_carrierNco.setFreq(channelFrequencyOffset, channelSampleRate);
|
||||
}
|
||||
|
||||
if ((channelSampleRate != m_channelSampleRate) || force)
|
||||
{
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorConsumed = false;
|
||||
m_interpolatorDistance = (Real) m_audioSampleRate / (Real) channelSampleRate;
|
||||
m_interpolator.create(48, m_audioSampleRate, m_settings.m_rfBandwidth / 2.2, 3.0);
|
||||
}
|
||||
|
||||
m_channelSampleRate = channelSampleRate;
|
||||
m_channelFrequencyOffset = channelFrequencyOffset;
|
||||
}
|
||||
|
||||
void M17ModSource::handleAudio()
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
unsigned int nbRead;
|
||||
|
||||
while ((nbRead = m_audioFifo.read(reinterpret_cast<quint8*>(&m_audioReadBuffer[m_audioReadBufferFill]), 4096)) != 0)
|
||||
{
|
||||
if (m_audioReadBufferFill + nbRead + 4096 < m_audioReadBuffer.size()) {
|
||||
m_audioReadBufferFill += nbRead;
|
||||
}
|
||||
}
|
||||
}
|
137
plugins/channeltx/modm17/m17modsource.h
Normal file
137
plugins/channeltx/modm17/m17modsource.h
Normal file
@ -0,0 +1,137 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_M17MODSOURCE_H
|
||||
#define INCLUDE_M17MODSOURCE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "dsp/channelsamplesource.h"
|
||||
#include "dsp/nco.h"
|
||||
#include "dsp/ncof.h"
|
||||
#include "dsp/interpolator.h"
|
||||
#include "dsp/firfilter.h"
|
||||
#include "dsp/filterrc.h"
|
||||
#include "util/movingaverage.h"
|
||||
#include "audio/audiofifo.h"
|
||||
|
||||
#include "m17modsettings.h"
|
||||
|
||||
class ChannelAPI;
|
||||
|
||||
class M17ModSource : public QObject, public ChannelSampleSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
M17ModSource();
|
||||
virtual ~M17ModSource();
|
||||
|
||||
virtual void pull(SampleVector::iterator begin, unsigned int nbSamples);
|
||||
virtual void pullOne(Sample& sample);
|
||||
virtual void prefetch(unsigned int nbSamples);
|
||||
|
||||
void setInputFileStream(std::ifstream *ifstream) { m_ifstream = ifstream; }
|
||||
AudioFifo *getAudioFifo() { return &m_audioFifo; }
|
||||
AudioFifo *getFeedbackAudioFifo() { return &m_feedbackAudioFifo; }
|
||||
void applyAudioSampleRate(int sampleRate);
|
||||
void applyFeedbackAudioSampleRate(int sampleRate);
|
||||
int getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
int getFeedbackAudioSampleRate() const { return m_feedbackAudioSampleRate; }
|
||||
void setChannel(ChannelAPI *channel) { m_channel = channel; }
|
||||
double getMagSq() const { return m_magsq; }
|
||||
void getLevels(qreal& rmsLevel, qreal& peakLevel, int& numSamples) const
|
||||
{
|
||||
rmsLevel = m_rmsLevel;
|
||||
peakLevel = m_peakLevelOut;
|
||||
numSamples = m_levelNbSamples;
|
||||
}
|
||||
void applySettings(const M17ModSettings& settings, bool force = false);
|
||||
void applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force = false);
|
||||
|
||||
private:
|
||||
int m_channelSampleRate;
|
||||
int m_channelFrequencyOffset;
|
||||
M17ModSettings m_settings;
|
||||
ChannelAPI *m_channel;
|
||||
|
||||
NCO m_carrierNco;
|
||||
NCOF m_toneNco;
|
||||
float m_modPhasor; //!< baseband modulator phasor
|
||||
Complex m_modSample;
|
||||
|
||||
Interpolator m_interpolator;
|
||||
Real m_interpolatorDistance;
|
||||
Real m_interpolatorDistanceRemain;
|
||||
bool m_interpolatorConsumed;
|
||||
|
||||
Interpolator m_feedbackInterpolator;
|
||||
Real m_feedbackInterpolatorDistance;
|
||||
Real m_feedbackInterpolatorDistanceRemain;
|
||||
bool m_feedbackInterpolatorConsumed;
|
||||
|
||||
QVector<qint16> m_demodBuffer;
|
||||
int m_demodBufferFill;
|
||||
|
||||
Lowpass<Real> m_lowpass;
|
||||
|
||||
double m_magsq;
|
||||
MovingAverageUtil<double, double, 16> m_movingAverage;
|
||||
|
||||
int m_audioSampleRate;
|
||||
AudioVector m_audioBuffer;
|
||||
unsigned int m_audioBufferFill;
|
||||
AudioVector m_audioReadBuffer;
|
||||
unsigned int m_audioReadBufferFill;
|
||||
AudioFifo m_audioFifo;
|
||||
|
||||
int m_feedbackAudioSampleRate;
|
||||
AudioVector m_feedbackAudioBuffer;
|
||||
uint m_feedbackAudioBufferFill;
|
||||
AudioFifo m_feedbackAudioFifo;
|
||||
|
||||
quint32 m_levelCalcCount;
|
||||
qreal m_rmsLevel;
|
||||
qreal m_peakLevelOut;
|
||||
Real m_peakLevel;
|
||||
Real m_levelSum;
|
||||
|
||||
std::ifstream *m_ifstream;
|
||||
|
||||
QMutex m_mutex;
|
||||
|
||||
static const int m_levelNbSamples;
|
||||
static const float m_preemphasis;
|
||||
|
||||
void processOneSample(Complex& ci);
|
||||
void pullAF(Real& sample);
|
||||
void pullAudio(unsigned int nbSamples);
|
||||
void pushFeedback(Real sample);
|
||||
void calculateLevel(Real& sample);
|
||||
void modulateSample();
|
||||
|
||||
private slots:
|
||||
void handleAudio();
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // INCLUDE_M17MODSOURCE_H
|
51
plugins/channeltx/modm17/m17modwebapiadapter.cpp
Normal file
51
plugins/channeltx/modm17/m17modwebapiadapter.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 "SWGChannelSettings.h"
|
||||
#include "dsp/cwkeyer.h"
|
||||
#include "m17mod.h"
|
||||
#include "m17modwebapiadapter.h"
|
||||
|
||||
M17ModWebAPIAdapter::M17ModWebAPIAdapter()
|
||||
{}
|
||||
|
||||
M17ModWebAPIAdapter::~M17ModWebAPIAdapter()
|
||||
{}
|
||||
|
||||
int M17ModWebAPIAdapter::webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) errorMessage;
|
||||
response.setM17ModSettings(new SWGSDRangel::SWGM17ModSettings());
|
||||
response.getM17ModSettings()->init();
|
||||
M17Mod::webapiFormatChannelSettings(response, m_settings);
|
||||
return 200;
|
||||
}
|
||||
|
||||
int M17ModWebAPIAdapter::webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage)
|
||||
{
|
||||
(void) force; // no action
|
||||
(void) errorMessage;
|
||||
M17Mod::webapiUpdateChannelSettings(m_settings, channelSettingsKeys, response);
|
||||
M17Mod::webapiFormatChannelSettings(response, m_settings);
|
||||
return 200;
|
||||
}
|
49
plugins/channeltx/modm17/m17modwebapiadapter.h
Normal file
49
plugins/channeltx/modm17/m17modwebapiadapter.h
Normal file
@ -0,0 +1,49 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2022 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 //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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_M17MOD_WEBAPIADAPTER_H
|
||||
#define INCLUDE_M17MOD_WEBAPIADAPTER_H
|
||||
|
||||
#include "channel/channelwebapiadapter.h"
|
||||
#include "m17modsettings.h"
|
||||
|
||||
/**
|
||||
* Standalone API adapter only for the settings
|
||||
*/
|
||||
class M17ModWebAPIAdapter : public ChannelWebAPIAdapter {
|
||||
public:
|
||||
M17ModWebAPIAdapter();
|
||||
virtual ~M17ModWebAPIAdapter();
|
||||
|
||||
virtual QByteArray serialize() const { return m_settings.serialize(); }
|
||||
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
|
||||
|
||||
virtual int webapiSettingsGet(
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
virtual int webapiSettingsPutPatch(
|
||||
bool force,
|
||||
const QStringList& channelSettingsKeys,
|
||||
SWGSDRangel::SWGChannelSettings& response,
|
||||
QString& errorMessage);
|
||||
|
||||
private:
|
||||
M17ModSettings m_settings;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_M17MOD_WEBAPIADAPTER_H
|
@ -3424,6 +3424,9 @@ margin-bottom: 20px;
|
||||
"M17DemodReport" : {
|
||||
"$ref" : "#/definitions/M17DemodReport"
|
||||
},
|
||||
"M17ModReport" : {
|
||||
"$ref" : "#/definitions/M17ModReport"
|
||||
},
|
||||
"NFMDemodReport" : {
|
||||
"$ref" : "#/definitions/NFMDemodReport"
|
||||
},
|
||||
@ -3579,6 +3582,9 @@ margin-bottom: 20px;
|
||||
"M17DemodSettings" : {
|
||||
"$ref" : "#/definitions/M17DemodSettings"
|
||||
},
|
||||
"M17ModSettings" : {
|
||||
"$ref" : "#/definitions/M17ModSettings"
|
||||
},
|
||||
"NFMDemodSettings" : {
|
||||
"$ref" : "#/definitions/NFMDemodSettings"
|
||||
},
|
||||
@ -8330,6 +8336,91 @@ margin-bottom: 20px;
|
||||
}
|
||||
},
|
||||
"description" : "M17Demod"
|
||||
};
|
||||
defs.M17ModReport = {
|
||||
"properties" : {
|
||||
"channelPowerDB" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "power transmitted in channel (dB)"
|
||||
},
|
||||
"audioSampleRate" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"channelSampleRate" : {
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"description" : "NFMMod"
|
||||
};
|
||||
defs.M17ModSettings = {
|
||||
"properties" : {
|
||||
"inputFrequencyOffset" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"rfBandwidth" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"fmDeviation" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"toneFrequency" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"volumeFactor" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"channelMute" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"playLoop" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"title" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"audioDeviceName" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"modAFInput" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"streamIndex" : {
|
||||
"type" : "integer",
|
||||
"description" : "MIMO channel. Not relevant when connected to SI (single Rx)."
|
||||
},
|
||||
"useReverseAPI" : {
|
||||
"type" : "integer",
|
||||
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
|
||||
},
|
||||
"reverseAPIAddress" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"reverseAPIPort" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"reverseAPIDeviceIndex" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"reverseAPIChannelIndex" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"channelMarker" : {
|
||||
"$ref" : "#/definitions/ChannelMarker"
|
||||
},
|
||||
"rollupState" : {
|
||||
"$ref" : "#/definitions/RollupState"
|
||||
}
|
||||
},
|
||||
"description" : "M17Mod"
|
||||
};
|
||||
defs.MapActions = {
|
||||
"properties" : {
|
||||
@ -56289,7 +56380,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2022-06-05T00:26:14.019+02:00
|
||||
Generated 2022-06-09T22:25:54.513+02:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -51,6 +51,8 @@ ChannelReport:
|
||||
$ref: "/doc/swagger/include/FreqTracker.yaml#/FreqTrackerReport"
|
||||
M17DemodReport:
|
||||
$ref: "/doc/swagger/include/M17Demod.yaml#/M17DemodReport"
|
||||
M17ModReport:
|
||||
$ref: "/doc/swagger/include/M17Mod.yaml#/M17ModReport"
|
||||
NFMDemodReport:
|
||||
$ref: "/doc/swagger/include/NFMDemod.yaml#/NFMDemodReport"
|
||||
NFMModReport:
|
||||
|
@ -69,6 +69,8 @@ ChannelSettings:
|
||||
$ref: "/doc/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModSettings"
|
||||
M17DemodSettings:
|
||||
$ref: "/doc/swagger/include/M17Demod.yaml#/M17DemodSettings"
|
||||
M17ModSettings:
|
||||
$ref: "/doc/swagger/include/M17Mod.yaml#/M17ModSettings"
|
||||
NFMDemodSettings:
|
||||
$ref: "/doc/swagger/include/NFMDemod.yaml#/NFMDemodSettings"
|
||||
NFMModSettings:
|
||||
|
60
sdrbase/resources/webapi/doc/swagger/include/M17Mod.yaml
Normal file
60
sdrbase/resources/webapi/doc/swagger/include/M17Mod.yaml
Normal file
@ -0,0 +1,60 @@
|
||||
M17ModSettings:
|
||||
description: M17Mod
|
||||
properties:
|
||||
inputFrequencyOffset:
|
||||
type: integer
|
||||
format: int64
|
||||
rfBandwidth:
|
||||
type: number
|
||||
format: float
|
||||
fmDeviation:
|
||||
type: number
|
||||
format: float
|
||||
toneFrequency:
|
||||
type: number
|
||||
format: float
|
||||
volumeFactor:
|
||||
type: number
|
||||
format: float
|
||||
channelMute:
|
||||
type: integer
|
||||
playLoop:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
audioDeviceName:
|
||||
type: string
|
||||
modAFInput:
|
||||
type: integer
|
||||
streamIndex:
|
||||
description: MIMO channel. Not relevant when connected to SI (single Rx).
|
||||
type: integer
|
||||
useReverseAPI:
|
||||
description: Synchronize with reverse API (1 for yes, 0 for no)
|
||||
type: integer
|
||||
reverseAPIAddress:
|
||||
type: string
|
||||
reverseAPIPort:
|
||||
type: integer
|
||||
reverseAPIDeviceIndex:
|
||||
type: integer
|
||||
reverseAPIChannelIndex:
|
||||
type: integer
|
||||
channelMarker:
|
||||
$ref: "/doc/swagger/include/ChannelMarker.yaml#/ChannelMarker"
|
||||
rollupState:
|
||||
$ref: "/doc/swagger/include/RollupState.yaml#/RollupState"
|
||||
|
||||
M17ModReport:
|
||||
description: NFMMod
|
||||
properties:
|
||||
channelPowerDB:
|
||||
description: power transmitted in channel (dB)
|
||||
type: number
|
||||
format: float
|
||||
audioSampleRate:
|
||||
type: integer
|
||||
channelSampleRate:
|
||||
type: integer
|
@ -4516,16 +4516,21 @@ bool WebAPIRequestMapper::getChannelSettings(
|
||||
channelSettings->setInterferometerSettings(new SWGSDRangel::SWGInterferometerSettings());
|
||||
channelSettings->getInterferometerSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "NFMDemodSettings")
|
||||
{
|
||||
channelSettings->setNfmDemodSettings(new SWGSDRangel::SWGNFMDemodSettings());
|
||||
channelSettings->getNfmDemodSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "M17DemodSettings")
|
||||
{
|
||||
channelSettings->setM17DemodSettings(new SWGSDRangel::SWGM17DemodSettings());
|
||||
channelSettings->getM17DemodSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "M17ModSettings")
|
||||
{
|
||||
channelSettings->setM17ModSettings(new SWGSDRangel::SWGM17ModSettings());
|
||||
channelSettings->getM17ModSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "NFMDemodSettings")
|
||||
{
|
||||
channelSettings->setNfmDemodSettings(new SWGSDRangel::SWGNFMDemodSettings());
|
||||
channelSettings->getNfmDemodSettings()->fromJsonObject(settingsJsonObject);
|
||||
}
|
||||
else if (channelSettingsKey == "NFMModSettings")
|
||||
{
|
||||
channelSettings->setNfmModSettings(new SWGSDRangel::SWGNFMModSettings());
|
||||
|
@ -48,6 +48,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelURIToSettingsKey = {
|
||||
{"sdrangel.channeltx.freedvmod", "FreeDVModSettings"},
|
||||
{"sdrangel.channel.freqtracker", "FreqTrackerSettings"},
|
||||
{"sdrangel.channel.m17demod", "M17DemodSettings"},
|
||||
{"sdrangel.channeltx.modm17", "M17ModSettings"},
|
||||
{"sdrangel.channel.nfmdemod", "NFMDemodSettings"},
|
||||
{"de.maintech.sdrangelove.channel.nfm", "NFMDemodSettings"}, // remap
|
||||
{"sdrangel.channeltx.modnfm", "NFMModSettings"},
|
||||
@ -155,6 +156,7 @@ const QMap<QString, QString> WebAPIUtils::m_channelTypeToSettingsKey = {
|
||||
{"FreqTracker", "FreqTrackerSettings"},
|
||||
{"IEEE_802_15_4_Mod", "IEEE_802_15_4_ModSettings"},
|
||||
{"M17Demod", "M17DemodSettings"},
|
||||
{"M17Mod", "M17ModSettings"},
|
||||
{"NFMDemod", "NFMDemodSettings"},
|
||||
{"NFMMod", "NFMModSettings"},
|
||||
{"NoiseFigure", "NoiseFigureSettings"},
|
||||
|
@ -51,6 +51,8 @@ ChannelReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/FreqTracker.yaml#/FreqTrackerReport"
|
||||
M17DemodReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/M17Demod.yaml#/M17DemodReport"
|
||||
M17ModReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/M17Mod.yaml#/M17ModReport"
|
||||
NFMDemodReport:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/NFMDemod.yaml#/NFMDemodReport"
|
||||
NFMModReport:
|
||||
|
@ -69,6 +69,8 @@ ChannelSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/IEEE_802_15_4_Mod.yaml#/IEEE_802_15_4_ModSettings"
|
||||
M17DemodSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/M17Demod.yaml#/M17DemodSettings"
|
||||
M17ModSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/M17Mod.yaml#/M17ModSettings"
|
||||
NFMDemodSettings:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/NFMDemod.yaml#/NFMDemodSettings"
|
||||
NFMModSettings:
|
||||
|
60
swagger/sdrangel/api/swagger/include/M17Mod.yaml
Normal file
60
swagger/sdrangel/api/swagger/include/M17Mod.yaml
Normal file
@ -0,0 +1,60 @@
|
||||
M17ModSettings:
|
||||
description: M17Mod
|
||||
properties:
|
||||
inputFrequencyOffset:
|
||||
type: integer
|
||||
format: int64
|
||||
rfBandwidth:
|
||||
type: number
|
||||
format: float
|
||||
fmDeviation:
|
||||
type: number
|
||||
format: float
|
||||
toneFrequency:
|
||||
type: number
|
||||
format: float
|
||||
volumeFactor:
|
||||
type: number
|
||||
format: float
|
||||
channelMute:
|
||||
type: integer
|
||||
playLoop:
|
||||
type: integer
|
||||
rgbColor:
|
||||
type: integer
|
||||
title:
|
||||
type: string
|
||||
audioDeviceName:
|
||||
type: string
|
||||
modAFInput:
|
||||
type: integer
|
||||
streamIndex:
|
||||
description: MIMO channel. Not relevant when connected to SI (single Rx).
|
||||
type: integer
|
||||
useReverseAPI:
|
||||
description: Synchronize with reverse API (1 for yes, 0 for no)
|
||||
type: integer
|
||||
reverseAPIAddress:
|
||||
type: string
|
||||
reverseAPIPort:
|
||||
type: integer
|
||||
reverseAPIDeviceIndex:
|
||||
type: integer
|
||||
reverseAPIChannelIndex:
|
||||
type: integer
|
||||
channelMarker:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/ChannelMarker.yaml#/ChannelMarker"
|
||||
rollupState:
|
||||
$ref: "http://swgserver:8081/api/swagger/include/RollupState.yaml#/RollupState"
|
||||
|
||||
M17ModReport:
|
||||
description: NFMMod
|
||||
properties:
|
||||
channelPowerDB:
|
||||
description: power transmitted in channel (dB)
|
||||
type: number
|
||||
format: float
|
||||
audioSampleRate:
|
||||
type: integer
|
||||
channelSampleRate:
|
||||
type: integer
|
@ -3424,6 +3424,9 @@ margin-bottom: 20px;
|
||||
"M17DemodReport" : {
|
||||
"$ref" : "#/definitions/M17DemodReport"
|
||||
},
|
||||
"M17ModReport" : {
|
||||
"$ref" : "#/definitions/M17ModReport"
|
||||
},
|
||||
"NFMDemodReport" : {
|
||||
"$ref" : "#/definitions/NFMDemodReport"
|
||||
},
|
||||
@ -3579,6 +3582,9 @@ margin-bottom: 20px;
|
||||
"M17DemodSettings" : {
|
||||
"$ref" : "#/definitions/M17DemodSettings"
|
||||
},
|
||||
"M17ModSettings" : {
|
||||
"$ref" : "#/definitions/M17ModSettings"
|
||||
},
|
||||
"NFMDemodSettings" : {
|
||||
"$ref" : "#/definitions/NFMDemodSettings"
|
||||
},
|
||||
@ -8330,6 +8336,91 @@ margin-bottom: 20px;
|
||||
}
|
||||
},
|
||||
"description" : "M17Demod"
|
||||
};
|
||||
defs.M17ModReport = {
|
||||
"properties" : {
|
||||
"channelPowerDB" : {
|
||||
"type" : "number",
|
||||
"format" : "float",
|
||||
"description" : "power transmitted in channel (dB)"
|
||||
},
|
||||
"audioSampleRate" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"channelSampleRate" : {
|
||||
"type" : "integer"
|
||||
}
|
||||
},
|
||||
"description" : "NFMMod"
|
||||
};
|
||||
defs.M17ModSettings = {
|
||||
"properties" : {
|
||||
"inputFrequencyOffset" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"rfBandwidth" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"fmDeviation" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"toneFrequency" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"volumeFactor" : {
|
||||
"type" : "number",
|
||||
"format" : "float"
|
||||
},
|
||||
"channelMute" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"playLoop" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"rgbColor" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"title" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"audioDeviceName" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"modAFInput" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"streamIndex" : {
|
||||
"type" : "integer",
|
||||
"description" : "MIMO channel. Not relevant when connected to SI (single Rx)."
|
||||
},
|
||||
"useReverseAPI" : {
|
||||
"type" : "integer",
|
||||
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
|
||||
},
|
||||
"reverseAPIAddress" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"reverseAPIPort" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"reverseAPIDeviceIndex" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"reverseAPIChannelIndex" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"channelMarker" : {
|
||||
"$ref" : "#/definitions/ChannelMarker"
|
||||
},
|
||||
"rollupState" : {
|
||||
"$ref" : "#/definitions/RollupState"
|
||||
}
|
||||
},
|
||||
"description" : "M17Mod"
|
||||
};
|
||||
defs.MapActions = {
|
||||
"properties" : {
|
||||
@ -56289,7 +56380,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2022-06-05T00:26:14.019+02:00
|
||||
Generated 2022-06-09T22:25:54.513+02:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -72,6 +72,8 @@ SWGChannelReport::SWGChannelReport() {
|
||||
m_freq_tracker_report_isSet = false;
|
||||
m17_demod_report = nullptr;
|
||||
m_m17_demod_report_isSet = false;
|
||||
m17_mod_report = nullptr;
|
||||
m_m17_mod_report_isSet = false;
|
||||
nfm_demod_report = nullptr;
|
||||
m_nfm_demod_report_isSet = false;
|
||||
nfm_mod_report = nullptr;
|
||||
@ -160,6 +162,8 @@ SWGChannelReport::init() {
|
||||
m_freq_tracker_report_isSet = false;
|
||||
m17_demod_report = new SWGM17DemodReport();
|
||||
m_m17_demod_report_isSet = false;
|
||||
m17_mod_report = new SWGM17ModReport();
|
||||
m_m17_mod_report_isSet = false;
|
||||
nfm_demod_report = new SWGNFMDemodReport();
|
||||
m_nfm_demod_report_isSet = false;
|
||||
nfm_mod_report = new SWGNFMModReport();
|
||||
@ -264,6 +268,9 @@ SWGChannelReport::cleanup() {
|
||||
if(m17_demod_report != nullptr) {
|
||||
delete m17_demod_report;
|
||||
}
|
||||
if(m17_mod_report != nullptr) {
|
||||
delete m17_mod_report;
|
||||
}
|
||||
if(nfm_demod_report != nullptr) {
|
||||
delete nfm_demod_report;
|
||||
}
|
||||
@ -375,6 +382,8 @@ SWGChannelReport::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&m17_demod_report, pJson["M17DemodReport"], "SWGM17DemodReport", "SWGM17DemodReport");
|
||||
|
||||
::SWGSDRangel::setValue(&m17_mod_report, pJson["M17ModReport"], "SWGM17ModReport", "SWGM17ModReport");
|
||||
|
||||
::SWGSDRangel::setValue(&nfm_demod_report, pJson["NFMDemodReport"], "SWGNFMDemodReport", "SWGNFMDemodReport");
|
||||
|
||||
::SWGSDRangel::setValue(&nfm_mod_report, pJson["NFMModReport"], "SWGNFMModReport", "SWGNFMModReport");
|
||||
@ -493,6 +502,9 @@ SWGChannelReport::asJsonObject() {
|
||||
if((m17_demod_report != nullptr) && (m17_demod_report->isSet())){
|
||||
toJsonValue(QString("M17DemodReport"), m17_demod_report, obj, QString("SWGM17DemodReport"));
|
||||
}
|
||||
if((m17_mod_report != nullptr) && (m17_mod_report->isSet())){
|
||||
toJsonValue(QString("M17ModReport"), m17_mod_report, obj, QString("SWGM17ModReport"));
|
||||
}
|
||||
if((nfm_demod_report != nullptr) && (nfm_demod_report->isSet())){
|
||||
toJsonValue(QString("NFMDemodReport"), nfm_demod_report, obj, QString("SWGNFMDemodReport"));
|
||||
}
|
||||
@ -771,6 +783,16 @@ SWGChannelReport::setM17DemodReport(SWGM17DemodReport* m17_demod_report) {
|
||||
this->m_m17_demod_report_isSet = true;
|
||||
}
|
||||
|
||||
SWGM17ModReport*
|
||||
SWGChannelReport::getM17ModReport() {
|
||||
return m17_mod_report;
|
||||
}
|
||||
void
|
||||
SWGChannelReport::setM17ModReport(SWGM17ModReport* m17_mod_report) {
|
||||
this->m17_mod_report = m17_mod_report;
|
||||
this->m_m17_mod_report_isSet = true;
|
||||
}
|
||||
|
||||
SWGNFMDemodReport*
|
||||
SWGChannelReport::getNfmDemodReport() {
|
||||
return nfm_demod_report;
|
||||
@ -1022,6 +1044,9 @@ SWGChannelReport::isSet(){
|
||||
if(m17_demod_report && m17_demod_report->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m17_mod_report && m17_mod_report->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(nfm_demod_report && nfm_demod_report->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "SWGFreqTrackerReport.h"
|
||||
#include "SWGIEEE_802_15_4_ModReport.h"
|
||||
#include "SWGM17DemodReport.h"
|
||||
#include "SWGM17ModReport.h"
|
||||
#include "SWGNFMDemodReport.h"
|
||||
#include "SWGNFMModReport.h"
|
||||
#include "SWGNoiseFigureReport.h"
|
||||
@ -146,6 +147,9 @@ public:
|
||||
SWGM17DemodReport* getM17DemodReport();
|
||||
void setM17DemodReport(SWGM17DemodReport* m17_demod_report);
|
||||
|
||||
SWGM17ModReport* getM17ModReport();
|
||||
void setM17ModReport(SWGM17ModReport* m17_mod_report);
|
||||
|
||||
SWGNFMDemodReport* getNfmDemodReport();
|
||||
void setNfmDemodReport(SWGNFMDemodReport* nfm_demod_report);
|
||||
|
||||
@ -270,6 +274,9 @@ private:
|
||||
SWGM17DemodReport* m17_demod_report;
|
||||
bool m_m17_demod_report_isSet;
|
||||
|
||||
SWGM17ModReport* m17_mod_report;
|
||||
bool m_m17_mod_report_isSet;
|
||||
|
||||
SWGNFMDemodReport* nfm_demod_report;
|
||||
bool m_nfm_demod_report_isSet;
|
||||
|
||||
|
@ -88,6 +88,8 @@ SWGChannelSettings::SWGChannelSettings() {
|
||||
m_ieee_802_15_4_mod_settings_isSet = false;
|
||||
m17_demod_settings = nullptr;
|
||||
m_m17_demod_settings_isSet = false;
|
||||
m17_mod_settings = nullptr;
|
||||
m_m17_mod_settings_isSet = false;
|
||||
nfm_demod_settings = nullptr;
|
||||
m_nfm_demod_settings_isSet = false;
|
||||
nfm_mod_settings = nullptr;
|
||||
@ -198,6 +200,8 @@ SWGChannelSettings::init() {
|
||||
m_ieee_802_15_4_mod_settings_isSet = false;
|
||||
m17_demod_settings = new SWGM17DemodSettings();
|
||||
m_m17_demod_settings_isSet = false;
|
||||
m17_mod_settings = new SWGM17ModSettings();
|
||||
m_m17_mod_settings_isSet = false;
|
||||
nfm_demod_settings = new SWGNFMDemodSettings();
|
||||
m_nfm_demod_settings_isSet = false;
|
||||
nfm_mod_settings = new SWGNFMModSettings();
|
||||
@ -328,6 +332,9 @@ SWGChannelSettings::cleanup() {
|
||||
if(m17_demod_settings != nullptr) {
|
||||
delete m17_demod_settings;
|
||||
}
|
||||
if(m17_mod_settings != nullptr) {
|
||||
delete m17_mod_settings;
|
||||
}
|
||||
if(nfm_demod_settings != nullptr) {
|
||||
delete nfm_demod_settings;
|
||||
}
|
||||
@ -464,6 +471,8 @@ SWGChannelSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&m17_demod_settings, pJson["M17DemodSettings"], "SWGM17DemodSettings", "SWGM17DemodSettings");
|
||||
|
||||
::SWGSDRangel::setValue(&m17_mod_settings, pJson["M17ModSettings"], "SWGM17ModSettings", "SWGM17ModSettings");
|
||||
|
||||
::SWGSDRangel::setValue(&nfm_demod_settings, pJson["NFMDemodSettings"], "SWGNFMDemodSettings", "SWGNFMDemodSettings");
|
||||
|
||||
::SWGSDRangel::setValue(&nfm_mod_settings, pJson["NFMModSettings"], "SWGNFMModSettings", "SWGNFMModSettings");
|
||||
@ -612,6 +621,9 @@ SWGChannelSettings::asJsonObject() {
|
||||
if((m17_demod_settings != nullptr) && (m17_demod_settings->isSet())){
|
||||
toJsonValue(QString("M17DemodSettings"), m17_demod_settings, obj, QString("SWGM17DemodSettings"));
|
||||
}
|
||||
if((m17_mod_settings != nullptr) && (m17_mod_settings->isSet())){
|
||||
toJsonValue(QString("M17ModSettings"), m17_mod_settings, obj, QString("SWGM17ModSettings"));
|
||||
}
|
||||
if((nfm_demod_settings != nullptr) && (nfm_demod_settings->isSet())){
|
||||
toJsonValue(QString("NFMDemodSettings"), nfm_demod_settings, obj, QString("SWGNFMDemodSettings"));
|
||||
}
|
||||
@ -979,6 +991,16 @@ SWGChannelSettings::setM17DemodSettings(SWGM17DemodSettings* m17_demod_settings)
|
||||
this->m_m17_demod_settings_isSet = true;
|
||||
}
|
||||
|
||||
SWGM17ModSettings*
|
||||
SWGChannelSettings::getM17ModSettings() {
|
||||
return m17_mod_settings;
|
||||
}
|
||||
void
|
||||
SWGChannelSettings::setM17ModSettings(SWGM17ModSettings* m17_mod_settings) {
|
||||
this->m17_mod_settings = m17_mod_settings;
|
||||
this->m_m17_mod_settings_isSet = true;
|
||||
}
|
||||
|
||||
SWGNFMDemodSettings*
|
||||
SWGChannelSettings::getNfmDemodSettings() {
|
||||
return nfm_demod_settings;
|
||||
@ -1284,6 +1306,9 @@ SWGChannelSettings::isSet(){
|
||||
if(m17_demod_settings && m17_demod_settings->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m17_mod_settings && m17_mod_settings->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(nfm_demod_settings && nfm_demod_settings->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "SWGLocalSinkSettings.h"
|
||||
#include "SWGLocalSourceSettings.h"
|
||||
#include "SWGM17DemodSettings.h"
|
||||
#include "SWGM17ModSettings.h"
|
||||
#include "SWGNFMDemodSettings.h"
|
||||
#include "SWGNFMModSettings.h"
|
||||
#include "SWGNoiseFigureSettings.h"
|
||||
@ -179,6 +180,9 @@ public:
|
||||
SWGM17DemodSettings* getM17DemodSettings();
|
||||
void setM17DemodSettings(SWGM17DemodSettings* m17_demod_settings);
|
||||
|
||||
SWGM17ModSettings* getM17ModSettings();
|
||||
void setM17ModSettings(SWGM17ModSettings* m17_mod_settings);
|
||||
|
||||
SWGNFMDemodSettings* getNfmDemodSettings();
|
||||
void setNfmDemodSettings(SWGNFMDemodSettings* nfm_demod_settings);
|
||||
|
||||
@ -336,6 +340,9 @@ private:
|
||||
SWGM17DemodSettings* m17_demod_settings;
|
||||
bool m_m17_demod_settings_isSet;
|
||||
|
||||
SWGM17ModSettings* m17_mod_settings;
|
||||
bool m_m17_mod_settings_isSet;
|
||||
|
||||
SWGNFMDemodSettings* nfm_demod_settings;
|
||||
bool m_nfm_demod_settings_isSet;
|
||||
|
||||
|
154
swagger/sdrangel/code/qt5/client/SWGM17ModReport.cpp
Normal file
154
swagger/sdrangel/code/qt5/client/SWGM17ModReport.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
#include "SWGM17ModReport.h"
|
||||
|
||||
#include "SWGHelpers.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
SWGM17ModReport::SWGM17ModReport(QString* json) {
|
||||
init();
|
||||
this->fromJson(*json);
|
||||
}
|
||||
|
||||
SWGM17ModReport::SWGM17ModReport() {
|
||||
channel_power_db = 0.0f;
|
||||
m_channel_power_db_isSet = false;
|
||||
audio_sample_rate = 0;
|
||||
m_audio_sample_rate_isSet = false;
|
||||
channel_sample_rate = 0;
|
||||
m_channel_sample_rate_isSet = false;
|
||||
}
|
||||
|
||||
SWGM17ModReport::~SWGM17ModReport() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
SWGM17ModReport::init() {
|
||||
channel_power_db = 0.0f;
|
||||
m_channel_power_db_isSet = false;
|
||||
audio_sample_rate = 0;
|
||||
m_audio_sample_rate_isSet = false;
|
||||
channel_sample_rate = 0;
|
||||
m_channel_sample_rate_isSet = false;
|
||||
}
|
||||
|
||||
void
|
||||
SWGM17ModReport::cleanup() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
SWGM17ModReport*
|
||||
SWGM17ModReport::fromJson(QString &json) {
|
||||
QByteArray array (json.toStdString().c_str());
|
||||
QJsonDocument doc = QJsonDocument::fromJson(array);
|
||||
QJsonObject jsonObject = doc.object();
|
||||
this->fromJsonObject(jsonObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
SWGM17ModReport::fromJsonObject(QJsonObject &pJson) {
|
||||
::SWGSDRangel::setValue(&channel_power_db, pJson["channelPowerDB"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&audio_sample_rate, pJson["audioSampleRate"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&channel_sample_rate, pJson["channelSampleRate"], "qint32", "");
|
||||
|
||||
}
|
||||
|
||||
QString
|
||||
SWGM17ModReport::asJson ()
|
||||
{
|
||||
QJsonObject* obj = this->asJsonObject();
|
||||
|
||||
QJsonDocument doc(*obj);
|
||||
QByteArray bytes = doc.toJson();
|
||||
delete obj;
|
||||
return QString(bytes);
|
||||
}
|
||||
|
||||
QJsonObject*
|
||||
SWGM17ModReport::asJsonObject() {
|
||||
QJsonObject* obj = new QJsonObject();
|
||||
if(m_channel_power_db_isSet){
|
||||
obj->insert("channelPowerDB", QJsonValue(channel_power_db));
|
||||
}
|
||||
if(m_audio_sample_rate_isSet){
|
||||
obj->insert("audioSampleRate", QJsonValue(audio_sample_rate));
|
||||
}
|
||||
if(m_channel_sample_rate_isSet){
|
||||
obj->insert("channelSampleRate", QJsonValue(channel_sample_rate));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
float
|
||||
SWGM17ModReport::getChannelPowerDb() {
|
||||
return channel_power_db;
|
||||
}
|
||||
void
|
||||
SWGM17ModReport::setChannelPowerDb(float channel_power_db) {
|
||||
this->channel_power_db = channel_power_db;
|
||||
this->m_channel_power_db_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModReport::getAudioSampleRate() {
|
||||
return audio_sample_rate;
|
||||
}
|
||||
void
|
||||
SWGM17ModReport::setAudioSampleRate(qint32 audio_sample_rate) {
|
||||
this->audio_sample_rate = audio_sample_rate;
|
||||
this->m_audio_sample_rate_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModReport::getChannelSampleRate() {
|
||||
return channel_sample_rate;
|
||||
}
|
||||
void
|
||||
SWGM17ModReport::setChannelSampleRate(qint32 channel_sample_rate) {
|
||||
this->channel_sample_rate = channel_sample_rate;
|
||||
this->m_channel_sample_rate_isSet = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SWGM17ModReport::isSet(){
|
||||
bool isObjectUpdated = false;
|
||||
do{
|
||||
if(m_channel_power_db_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_audio_sample_rate_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_channel_sample_rate_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
}while(false);
|
||||
return isObjectUpdated;
|
||||
}
|
||||
}
|
||||
|
70
swagger/sdrangel/code/qt5/client/SWGM17ModReport.h
Normal file
70
swagger/sdrangel/code/qt5/client/SWGM17ModReport.h
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SWGM17ModReport.h
|
||||
*
|
||||
* NFMMod
|
||||
*/
|
||||
|
||||
#ifndef SWGM17ModReport_H_
|
||||
#define SWGM17ModReport_H_
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
|
||||
#include "SWGObject.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
class SWG_API SWGM17ModReport: public SWGObject {
|
||||
public:
|
||||
SWGM17ModReport();
|
||||
SWGM17ModReport(QString* json);
|
||||
virtual ~SWGM17ModReport();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
virtual QString asJson () override;
|
||||
virtual QJsonObject* asJsonObject() override;
|
||||
virtual void fromJsonObject(QJsonObject &json) override;
|
||||
virtual SWGM17ModReport* fromJson(QString &jsonString) override;
|
||||
|
||||
float getChannelPowerDb();
|
||||
void setChannelPowerDb(float channel_power_db);
|
||||
|
||||
qint32 getAudioSampleRate();
|
||||
void setAudioSampleRate(qint32 audio_sample_rate);
|
||||
|
||||
qint32 getChannelSampleRate();
|
||||
void setChannelSampleRate(qint32 channel_sample_rate);
|
||||
|
||||
|
||||
virtual bool isSet() override;
|
||||
|
||||
private:
|
||||
float channel_power_db;
|
||||
bool m_channel_power_db_isSet;
|
||||
|
||||
qint32 audio_sample_rate;
|
||||
bool m_audio_sample_rate_isSet;
|
||||
|
||||
qint32 channel_sample_rate;
|
||||
bool m_channel_sample_rate_isSet;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SWGM17ModReport_H_ */
|
532
swagger/sdrangel/code/qt5/client/SWGM17ModSettings.cpp
Normal file
532
swagger/sdrangel/code/qt5/client/SWGM17ModSettings.cpp
Normal file
@ -0,0 +1,532 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
#include "SWGM17ModSettings.h"
|
||||
|
||||
#include "SWGHelpers.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
SWGM17ModSettings::SWGM17ModSettings(QString* json) {
|
||||
init();
|
||||
this->fromJson(*json);
|
||||
}
|
||||
|
||||
SWGM17ModSettings::SWGM17ModSettings() {
|
||||
input_frequency_offset = 0L;
|
||||
m_input_frequency_offset_isSet = false;
|
||||
rf_bandwidth = 0.0f;
|
||||
m_rf_bandwidth_isSet = false;
|
||||
fm_deviation = 0.0f;
|
||||
m_fm_deviation_isSet = false;
|
||||
tone_frequency = 0.0f;
|
||||
m_tone_frequency_isSet = false;
|
||||
volume_factor = 0.0f;
|
||||
m_volume_factor_isSet = false;
|
||||
channel_mute = 0;
|
||||
m_channel_mute_isSet = false;
|
||||
play_loop = 0;
|
||||
m_play_loop_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = nullptr;
|
||||
m_title_isSet = false;
|
||||
audio_device_name = nullptr;
|
||||
m_audio_device_name_isSet = false;
|
||||
mod_af_input = 0;
|
||||
m_mod_af_input_isSet = false;
|
||||
stream_index = 0;
|
||||
m_stream_index_isSet = false;
|
||||
use_reverse_api = 0;
|
||||
m_use_reverse_api_isSet = false;
|
||||
reverse_api_address = nullptr;
|
||||
m_reverse_api_address_isSet = false;
|
||||
reverse_api_port = 0;
|
||||
m_reverse_api_port_isSet = false;
|
||||
reverse_api_device_index = 0;
|
||||
m_reverse_api_device_index_isSet = false;
|
||||
reverse_api_channel_index = 0;
|
||||
m_reverse_api_channel_index_isSet = false;
|
||||
channel_marker = nullptr;
|
||||
m_channel_marker_isSet = false;
|
||||
rollup_state = nullptr;
|
||||
m_rollup_state_isSet = false;
|
||||
}
|
||||
|
||||
SWGM17ModSettings::~SWGM17ModSettings() {
|
||||
this->cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
SWGM17ModSettings::init() {
|
||||
input_frequency_offset = 0L;
|
||||
m_input_frequency_offset_isSet = false;
|
||||
rf_bandwidth = 0.0f;
|
||||
m_rf_bandwidth_isSet = false;
|
||||
fm_deviation = 0.0f;
|
||||
m_fm_deviation_isSet = false;
|
||||
tone_frequency = 0.0f;
|
||||
m_tone_frequency_isSet = false;
|
||||
volume_factor = 0.0f;
|
||||
m_volume_factor_isSet = false;
|
||||
channel_mute = 0;
|
||||
m_channel_mute_isSet = false;
|
||||
play_loop = 0;
|
||||
m_play_loop_isSet = false;
|
||||
rgb_color = 0;
|
||||
m_rgb_color_isSet = false;
|
||||
title = new QString("");
|
||||
m_title_isSet = false;
|
||||
audio_device_name = new QString("");
|
||||
m_audio_device_name_isSet = false;
|
||||
mod_af_input = 0;
|
||||
m_mod_af_input_isSet = false;
|
||||
stream_index = 0;
|
||||
m_stream_index_isSet = false;
|
||||
use_reverse_api = 0;
|
||||
m_use_reverse_api_isSet = false;
|
||||
reverse_api_address = new QString("");
|
||||
m_reverse_api_address_isSet = false;
|
||||
reverse_api_port = 0;
|
||||
m_reverse_api_port_isSet = false;
|
||||
reverse_api_device_index = 0;
|
||||
m_reverse_api_device_index_isSet = false;
|
||||
reverse_api_channel_index = 0;
|
||||
m_reverse_api_channel_index_isSet = false;
|
||||
channel_marker = new SWGChannelMarker();
|
||||
m_channel_marker_isSet = false;
|
||||
rollup_state = new SWGRollupState();
|
||||
m_rollup_state_isSet = false;
|
||||
}
|
||||
|
||||
void
|
||||
SWGM17ModSettings::cleanup() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
if(audio_device_name != nullptr) {
|
||||
delete audio_device_name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(reverse_api_address != nullptr) {
|
||||
delete reverse_api_address;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(channel_marker != nullptr) {
|
||||
delete channel_marker;
|
||||
}
|
||||
if(rollup_state != nullptr) {
|
||||
delete rollup_state;
|
||||
}
|
||||
}
|
||||
|
||||
SWGM17ModSettings*
|
||||
SWGM17ModSettings::fromJson(QString &json) {
|
||||
QByteArray array (json.toStdString().c_str());
|
||||
QJsonDocument doc = QJsonDocument::fromJson(array);
|
||||
QJsonObject jsonObject = doc.object();
|
||||
this->fromJsonObject(jsonObject);
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
SWGM17ModSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
::SWGSDRangel::setValue(&input_frequency_offset, pJson["inputFrequencyOffset"], "qint64", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rf_bandwidth, pJson["rfBandwidth"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&fm_deviation, pJson["fmDeviation"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&tone_frequency, pJson["toneFrequency"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&volume_factor, pJson["volumeFactor"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&channel_mute, pJson["channelMute"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&play_loop, pJson["playLoop"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&audio_device_name, pJson["audioDeviceName"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&mod_af_input, pJson["modAFInput"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&stream_index, pJson["streamIndex"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_channel_index, pJson["reverseAPIChannelIndex"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&channel_marker, pJson["channelMarker"], "SWGChannelMarker", "SWGChannelMarker");
|
||||
|
||||
::SWGSDRangel::setValue(&rollup_state, pJson["rollupState"], "SWGRollupState", "SWGRollupState");
|
||||
|
||||
}
|
||||
|
||||
QString
|
||||
SWGM17ModSettings::asJson ()
|
||||
{
|
||||
QJsonObject* obj = this->asJsonObject();
|
||||
|
||||
QJsonDocument doc(*obj);
|
||||
QByteArray bytes = doc.toJson();
|
||||
delete obj;
|
||||
return QString(bytes);
|
||||
}
|
||||
|
||||
QJsonObject*
|
||||
SWGM17ModSettings::asJsonObject() {
|
||||
QJsonObject* obj = new QJsonObject();
|
||||
if(m_input_frequency_offset_isSet){
|
||||
obj->insert("inputFrequencyOffset", QJsonValue(input_frequency_offset));
|
||||
}
|
||||
if(m_rf_bandwidth_isSet){
|
||||
obj->insert("rfBandwidth", QJsonValue(rf_bandwidth));
|
||||
}
|
||||
if(m_fm_deviation_isSet){
|
||||
obj->insert("fmDeviation", QJsonValue(fm_deviation));
|
||||
}
|
||||
if(m_tone_frequency_isSet){
|
||||
obj->insert("toneFrequency", QJsonValue(tone_frequency));
|
||||
}
|
||||
if(m_volume_factor_isSet){
|
||||
obj->insert("volumeFactor", QJsonValue(volume_factor));
|
||||
}
|
||||
if(m_channel_mute_isSet){
|
||||
obj->insert("channelMute", QJsonValue(channel_mute));
|
||||
}
|
||||
if(m_play_loop_isSet){
|
||||
obj->insert("playLoop", QJsonValue(play_loop));
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
obj->insert("rgbColor", QJsonValue(rgb_color));
|
||||
}
|
||||
if(title != nullptr && *title != QString("")){
|
||||
toJsonValue(QString("title"), title, obj, QString("QString"));
|
||||
}
|
||||
if(audio_device_name != nullptr && *audio_device_name != QString("")){
|
||||
toJsonValue(QString("audioDeviceName"), audio_device_name, obj, QString("QString"));
|
||||
}
|
||||
if(m_mod_af_input_isSet){
|
||||
obj->insert("modAFInput", QJsonValue(mod_af_input));
|
||||
}
|
||||
if(m_stream_index_isSet){
|
||||
obj->insert("streamIndex", QJsonValue(stream_index));
|
||||
}
|
||||
if(m_use_reverse_api_isSet){
|
||||
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
|
||||
}
|
||||
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){
|
||||
toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString"));
|
||||
}
|
||||
if(m_reverse_api_port_isSet){
|
||||
obj->insert("reverseAPIPort", QJsonValue(reverse_api_port));
|
||||
}
|
||||
if(m_reverse_api_device_index_isSet){
|
||||
obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index));
|
||||
}
|
||||
if(m_reverse_api_channel_index_isSet){
|
||||
obj->insert("reverseAPIChannelIndex", QJsonValue(reverse_api_channel_index));
|
||||
}
|
||||
if((channel_marker != nullptr) && (channel_marker->isSet())){
|
||||
toJsonValue(QString("channelMarker"), channel_marker, obj, QString("SWGChannelMarker"));
|
||||
}
|
||||
if((rollup_state != nullptr) && (rollup_state->isSet())){
|
||||
toJsonValue(QString("rollupState"), rollup_state, obj, QString("SWGRollupState"));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
qint64
|
||||
SWGM17ModSettings::getInputFrequencyOffset() {
|
||||
return input_frequency_offset;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setInputFrequencyOffset(qint64 input_frequency_offset) {
|
||||
this->input_frequency_offset = input_frequency_offset;
|
||||
this->m_input_frequency_offset_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGM17ModSettings::getRfBandwidth() {
|
||||
return rf_bandwidth;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setRfBandwidth(float rf_bandwidth) {
|
||||
this->rf_bandwidth = rf_bandwidth;
|
||||
this->m_rf_bandwidth_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGM17ModSettings::getFmDeviation() {
|
||||
return fm_deviation;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setFmDeviation(float fm_deviation) {
|
||||
this->fm_deviation = fm_deviation;
|
||||
this->m_fm_deviation_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGM17ModSettings::getToneFrequency() {
|
||||
return tone_frequency;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setToneFrequency(float tone_frequency) {
|
||||
this->tone_frequency = tone_frequency;
|
||||
this->m_tone_frequency_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGM17ModSettings::getVolumeFactor() {
|
||||
return volume_factor;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setVolumeFactor(float volume_factor) {
|
||||
this->volume_factor = volume_factor;
|
||||
this->m_volume_factor_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getChannelMute() {
|
||||
return channel_mute;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setChannelMute(qint32 channel_mute) {
|
||||
this->channel_mute = channel_mute;
|
||||
this->m_channel_mute_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getPlayLoop() {
|
||||
return play_loop;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setPlayLoop(qint32 play_loop) {
|
||||
this->play_loop = play_loop;
|
||||
this->m_play_loop_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getRgbColor() {
|
||||
return rgb_color;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setRgbColor(qint32 rgb_color) {
|
||||
this->rgb_color = rgb_color;
|
||||
this->m_rgb_color_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGM17ModSettings::getTitle() {
|
||||
return title;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setTitle(QString* title) {
|
||||
this->title = title;
|
||||
this->m_title_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGM17ModSettings::getAudioDeviceName() {
|
||||
return audio_device_name;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setAudioDeviceName(QString* audio_device_name) {
|
||||
this->audio_device_name = audio_device_name;
|
||||
this->m_audio_device_name_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getModAfInput() {
|
||||
return mod_af_input;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setModAfInput(qint32 mod_af_input) {
|
||||
this->mod_af_input = mod_af_input;
|
||||
this->m_mod_af_input_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getStreamIndex() {
|
||||
return stream_index;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setStreamIndex(qint32 stream_index) {
|
||||
this->stream_index = stream_index;
|
||||
this->m_stream_index_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getUseReverseApi() {
|
||||
return use_reverse_api;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setUseReverseApi(qint32 use_reverse_api) {
|
||||
this->use_reverse_api = use_reverse_api;
|
||||
this->m_use_reverse_api_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGM17ModSettings::getReverseApiAddress() {
|
||||
return reverse_api_address;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setReverseApiAddress(QString* reverse_api_address) {
|
||||
this->reverse_api_address = reverse_api_address;
|
||||
this->m_reverse_api_address_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getReverseApiPort() {
|
||||
return reverse_api_port;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setReverseApiPort(qint32 reverse_api_port) {
|
||||
this->reverse_api_port = reverse_api_port;
|
||||
this->m_reverse_api_port_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getReverseApiDeviceIndex() {
|
||||
return reverse_api_device_index;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
|
||||
this->reverse_api_device_index = reverse_api_device_index;
|
||||
this->m_reverse_api_device_index_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGM17ModSettings::getReverseApiChannelIndex() {
|
||||
return reverse_api_channel_index;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
|
||||
this->reverse_api_channel_index = reverse_api_channel_index;
|
||||
this->m_reverse_api_channel_index_isSet = true;
|
||||
}
|
||||
|
||||
SWGChannelMarker*
|
||||
SWGM17ModSettings::getChannelMarker() {
|
||||
return channel_marker;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setChannelMarker(SWGChannelMarker* channel_marker) {
|
||||
this->channel_marker = channel_marker;
|
||||
this->m_channel_marker_isSet = true;
|
||||
}
|
||||
|
||||
SWGRollupState*
|
||||
SWGM17ModSettings::getRollupState() {
|
||||
return rollup_state;
|
||||
}
|
||||
void
|
||||
SWGM17ModSettings::setRollupState(SWGRollupState* rollup_state) {
|
||||
this->rollup_state = rollup_state;
|
||||
this->m_rollup_state_isSet = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SWGM17ModSettings::isSet(){
|
||||
bool isObjectUpdated = false;
|
||||
do{
|
||||
if(m_input_frequency_offset_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rf_bandwidth_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_fm_deviation_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_tone_frequency_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_volume_factor_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_channel_mute_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_play_loop_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_rgb_color_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(title && *title != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(audio_device_name && *audio_device_name != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_mod_af_input_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_stream_index_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_reverse_api_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(reverse_api_address && *reverse_api_address != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_reverse_api_port_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_reverse_api_device_index_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_reverse_api_channel_index_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(channel_marker && channel_marker->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(rollup_state && rollup_state->isSet()){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
}while(false);
|
||||
return isObjectUpdated;
|
||||
}
|
||||
}
|
||||
|
169
swagger/sdrangel/code/qt5/client/SWGM17ModSettings.h
Normal file
169
swagger/sdrangel/code/qt5/client/SWGM17ModSettings.h
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
* SDRangel
|
||||
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
|
||||
*
|
||||
* OpenAPI spec version: 7.0.0
|
||||
* Contact: f4exb06@gmail.com
|
||||
*
|
||||
* NOTE: This class is auto generated by the swagger code generator program.
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SWGM17ModSettings.h
|
||||
*
|
||||
* M17Mod
|
||||
*/
|
||||
|
||||
#ifndef SWGM17ModSettings_H_
|
||||
#define SWGM17ModSettings_H_
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
#include "SWGChannelMarker.h"
|
||||
#include "SWGRollupState.h"
|
||||
#include <QString>
|
||||
|
||||
#include "SWGObject.h"
|
||||
#include "export.h"
|
||||
|
||||
namespace SWGSDRangel {
|
||||
|
||||
class SWG_API SWGM17ModSettings: public SWGObject {
|
||||
public:
|
||||
SWGM17ModSettings();
|
||||
SWGM17ModSettings(QString* json);
|
||||
virtual ~SWGM17ModSettings();
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
virtual QString asJson () override;
|
||||
virtual QJsonObject* asJsonObject() override;
|
||||
virtual void fromJsonObject(QJsonObject &json) override;
|
||||
virtual SWGM17ModSettings* fromJson(QString &jsonString) override;
|
||||
|
||||
qint64 getInputFrequencyOffset();
|
||||
void setInputFrequencyOffset(qint64 input_frequency_offset);
|
||||
|
||||
float getRfBandwidth();
|
||||
void setRfBandwidth(float rf_bandwidth);
|
||||
|
||||
float getFmDeviation();
|
||||
void setFmDeviation(float fm_deviation);
|
||||
|
||||
float getToneFrequency();
|
||||
void setToneFrequency(float tone_frequency);
|
||||
|
||||
float getVolumeFactor();
|
||||
void setVolumeFactor(float volume_factor);
|
||||
|
||||
qint32 getChannelMute();
|
||||
void setChannelMute(qint32 channel_mute);
|
||||
|
||||
qint32 getPlayLoop();
|
||||
void setPlayLoop(qint32 play_loop);
|
||||
|
||||
qint32 getRgbColor();
|
||||
void setRgbColor(qint32 rgb_color);
|
||||
|
||||
QString* getTitle();
|
||||
void setTitle(QString* title);
|
||||
|
||||
QString* getAudioDeviceName();
|
||||
void setAudioDeviceName(QString* audio_device_name);
|
||||
|
||||
qint32 getModAfInput();
|
||||
void setModAfInput(qint32 mod_af_input);
|
||||
|
||||
qint32 getStreamIndex();
|
||||
void setStreamIndex(qint32 stream_index);
|
||||
|
||||
qint32 getUseReverseApi();
|
||||
void setUseReverseApi(qint32 use_reverse_api);
|
||||
|
||||
QString* getReverseApiAddress();
|
||||
void setReverseApiAddress(QString* reverse_api_address);
|
||||
|
||||
qint32 getReverseApiPort();
|
||||
void setReverseApiPort(qint32 reverse_api_port);
|
||||
|
||||
qint32 getReverseApiDeviceIndex();
|
||||
void setReverseApiDeviceIndex(qint32 reverse_api_device_index);
|
||||
|
||||
qint32 getReverseApiChannelIndex();
|
||||
void setReverseApiChannelIndex(qint32 reverse_api_channel_index);
|
||||
|
||||
SWGChannelMarker* getChannelMarker();
|
||||
void setChannelMarker(SWGChannelMarker* channel_marker);
|
||||
|
||||
SWGRollupState* getRollupState();
|
||||
void setRollupState(SWGRollupState* rollup_state);
|
||||
|
||||
|
||||
virtual bool isSet() override;
|
||||
|
||||
private:
|
||||
qint64 input_frequency_offset;
|
||||
bool m_input_frequency_offset_isSet;
|
||||
|
||||
float rf_bandwidth;
|
||||
bool m_rf_bandwidth_isSet;
|
||||
|
||||
float fm_deviation;
|
||||
bool m_fm_deviation_isSet;
|
||||
|
||||
float tone_frequency;
|
||||
bool m_tone_frequency_isSet;
|
||||
|
||||
float volume_factor;
|
||||
bool m_volume_factor_isSet;
|
||||
|
||||
qint32 channel_mute;
|
||||
bool m_channel_mute_isSet;
|
||||
|
||||
qint32 play_loop;
|
||||
bool m_play_loop_isSet;
|
||||
|
||||
qint32 rgb_color;
|
||||
bool m_rgb_color_isSet;
|
||||
|
||||
QString* title;
|
||||
bool m_title_isSet;
|
||||
|
||||
QString* audio_device_name;
|
||||
bool m_audio_device_name_isSet;
|
||||
|
||||
qint32 mod_af_input;
|
||||
bool m_mod_af_input_isSet;
|
||||
|
||||
qint32 stream_index;
|
||||
bool m_stream_index_isSet;
|
||||
|
||||
qint32 use_reverse_api;
|
||||
bool m_use_reverse_api_isSet;
|
||||
|
||||
QString* reverse_api_address;
|
||||
bool m_reverse_api_address_isSet;
|
||||
|
||||
qint32 reverse_api_port;
|
||||
bool m_reverse_api_port_isSet;
|
||||
|
||||
qint32 reverse_api_device_index;
|
||||
bool m_reverse_api_device_index_isSet;
|
||||
|
||||
qint32 reverse_api_channel_index;
|
||||
bool m_reverse_api_channel_index_isSet;
|
||||
|
||||
SWGChannelMarker* channel_marker;
|
||||
bool m_channel_marker_isSet;
|
||||
|
||||
SWGRollupState* rollup_state;
|
||||
bool m_rollup_state_isSet;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* SWGM17ModSettings_H_ */
|
@ -185,6 +185,8 @@
|
||||
#include "SWGLoggingInfo.h"
|
||||
#include "SWGM17DemodReport.h"
|
||||
#include "SWGM17DemodSettings.h"
|
||||
#include "SWGM17ModReport.h"
|
||||
#include "SWGM17ModSettings.h"
|
||||
#include "SWGMapActions.h"
|
||||
#include "SWGMapAnimation.h"
|
||||
#include "SWGMapCoordinate.h"
|
||||
@ -1192,6 +1194,16 @@ namespace SWGSDRangel {
|
||||
obj->init();
|
||||
return obj;
|
||||
}
|
||||
if(QString("SWGM17ModReport").compare(type) == 0) {
|
||||
SWGM17ModReport *obj = new SWGM17ModReport();
|
||||
obj->init();
|
||||
return obj;
|
||||
}
|
||||
if(QString("SWGM17ModSettings").compare(type) == 0) {
|
||||
SWGM17ModSettings *obj = new SWGM17ModSettings();
|
||||
obj->init();
|
||||
return obj;
|
||||
}
|
||||
if(QString("SWGMapActions").compare(type) == 0) {
|
||||
SWGMapActions *obj = new SWGMapActions();
|
||||
obj->init();
|
||||
|
Loading…
x
Reference in New Issue
Block a user