Added the Local Source plugin

pull/349/head
f4exb 2019-05-10 13:20:30 +02:00
rodzic 6d5d77dc6c
commit ba4c8d7a68
20 zmienionych plików z 2529 dodań i 1 usunięć

Wyświetl plik

@ -124,7 +124,7 @@ LocalSinkGUI::LocalSinkGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseb
m_channelMarker.blockSignals(true);
m_channelMarker.setColor(m_settings.m_rgbColor);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle("Local source");
m_channelMarker.setTitle("Local Sink");
m_channelMarker.blockSignals(false);
m_channelMarker.setVisible(true); // activate signal on the last setting only

Wyświetl plik

@ -5,6 +5,7 @@ add_subdirectory(modnfm)
add_subdirectory(modssb)
add_subdirectory(modwfm)
add_subdirectory(udpsource)
add_subdirectory(localsource)
find_package(CM256cc)
if(CM256CC_FOUND)

Wyświetl plik

@ -0,0 +1,52 @@
project(localsource)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(localsource_SOURCES
localsource.cpp
localsourcethread.cpp
localsourcegui.cpp
localsourceplugin.cpp
localsourcesettings.cpp
)
set(localsource_HEADERS
localsource.h
localsourcethread.h
localsourcegui.h
localsourceplugin.h
localsourcesettings.h
)
set(localsource_FORMS
localsourcegui.ui
)
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
qt5_wrap_ui(localsource_FORMS_HEADERS ${localsource_FORMS})
add_library(localsource SHARED
${localsource_SOURCES}
${localsource_HEADERS_MOC}
${localsource_FORMS_HEADERS}
)
target_include_directories(localsource PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
target_link_libraries(localsource
${QT_LIBRARIES}
sdrbase
sdrgui
swagger
)
target_link_libraries(localsource Qt5::Core Qt5::Widgets Qt5::Network)
install(TARGETS localsource DESTINATION lib/plugins/channeltx)

Wyświetl plik

@ -0,0 +1,556 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "localsource.h"
#include <boost/crc.hpp>
#include <boost/cstdint.hpp>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGChannelSettings.h"
#include "util/simpleserializer.h"
#include "dsp/threadedbasebandsamplesource.h"
#include "dsp/upchannelizer.h"
#include "dsp/dspcommands.h"
#include "dsp/dspdevicesinkengine.h"
#include "dsp/dspengine.h"
#include "dsp/devicesamplesink.h"
#include "dsp/hbfilterchainconverter.h"
#include "device/deviceapi.h"
#include "localsourcethread.h"
MESSAGE_CLASS_DEFINITION(LocalSource::MsgConfigureLocalSource, Message)
MESSAGE_CLASS_DEFINITION(LocalSource::MsgSampleRateNotification, Message)
MESSAGE_CLASS_DEFINITION(LocalSource::MsgConfigureChannelizer, Message)
const QString LocalSource::m_channelIdURI = "sdrangel.channel.localsource";
const QString LocalSource::m_channelId = "LocalSource";
LocalSource::LocalSource(DeviceAPI *deviceAPI) :
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
m_deviceAPI(deviceAPI),
m_running(false),
m_sinkThread(nullptr),
m_localSampleSourceFifo(nullptr),
m_chunkSize(0),
m_localSamplesIndex(0),
m_localSamplesIndexOffset(0),
m_centerFrequency(0),
m_frequencyOffset(0),
m_sampleRate(48000),
m_deviceSampleRate(48000)
{
setObjectName(m_channelId);
m_channelizer = new UpChannelizer(this);
m_threadedChannelizer = new ThreadedBasebandSampleSource(m_channelizer, this);
m_deviceAPI->addChannelSource(m_threadedChannelizer);
m_deviceAPI->addChannelSourceAPI(this);
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
LocalSource::~LocalSource()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
m_deviceAPI->removeChannelSourceAPI(this);
m_deviceAPI->removeChannelSource(m_threadedChannelizer);
delete m_threadedChannelizer;
delete m_channelizer;
}
void LocalSource::pull(Sample& sample)
{
sample = m_localSamples[m_localSamplesIndex + m_localSamplesIndexOffset];
if (m_localSamplesIndex < m_chunkSize - 1)
{
m_localSamplesIndex++;
}
else
{
m_localSamplesIndex = 0;
if (m_localSamplesIndexOffset == 0) {
m_localSamplesIndexOffset = m_chunkSize;
} else {
m_localSamplesIndexOffset = 0;
}
emit pullSamples(m_chunkSize);
}
}
void LocalSource::processSamples(unsigned int offset)
{
if (m_localSampleSourceFifo)
{
int destOffset = (m_localSamplesIndexOffset == 0 ? m_chunkSize : 0);
SampleVector::iterator beginSource;
SampleVector::iterator beginDestination = m_localSamples.begin() + destOffset;
m_localSampleSourceFifo->setIteratorFromOffset(beginSource, offset);
std::copy(beginSource, beginSource + m_chunkSize, beginDestination);
}
}
void LocalSource::pullAudio(int nbSamples)
{
(void) nbSamples;
}
void LocalSource::start()
{
qDebug("LocalSource::start");
if (m_running) {
stop();
}
m_sinkThread = new LocalSourceThread();
DeviceSampleSink *deviceSink = getLocalDevice(m_settings.m_localDeviceIndex);
if (deviceSink)
{
m_localSampleSourceFifo = deviceSink->getSampleFifo();
m_chunkSize = m_localSampleSourceFifo->size() / 16;
m_localSamples.resize(2*m_chunkSize);
m_localSamplesIndex = 0;
m_sinkThread->setSampleFifo(m_localSampleSourceFifo);
}
else
{
m_localSampleSourceFifo = nullptr;
}
connect(this,
SIGNAL(pullSamples(unsigned int)),
m_sinkThread,
SLOT(pullSamples(unsigned int)),
Qt::QueuedConnection);
connect(m_sinkThread,
SIGNAL(samplesAvailable(int)),
this,
SLOT(pprocessSamples(int)),
Qt::QueuedConnection);
m_sinkThread->startStop(true);
m_running = true;
}
void LocalSource::stop()
{
qDebug("LocalSource::stop");
if (m_sinkThread != 0)
{
m_sinkThread->startStop(false);
m_sinkThread->deleteLater();
m_sinkThread = 0;
}
m_running = false;
}
bool LocalSource::handleMessage(const Message& cmd)
{
if (UpChannelizer::MsgChannelizerNotification::match(cmd))
{
UpChannelizer::MsgChannelizerNotification& notif = (UpChannelizer::MsgChannelizerNotification&) cmd;
qDebug() << "LocalSource::handleMessage: MsgChannelizerNotification:"
<< " channelSampleRate: " << notif.getSampleRate()
<< " offsetFrequency: " << notif.getFrequencyOffset();
if (notif.getSampleRate() > 0)
{
setSampleRate(notif.getSampleRate());
}
return true;
}
else if (DSPSignalNotification::match(cmd))
{
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
qDebug() << "LocalSource::handleMessage: DSPSignalNotification:"
<< " inputSampleRate: " << notif.getSampleRate()
<< " centerFrequency: " << notif.getCenterFrequency();
setCenterFrequency(notif.getCenterFrequency());
m_deviceSampleRate = notif.getSampleRate();
calculateFrequencyOffset(); // This is when device sample rate changes
propagateSampleRateAndFrequency(m_settings.m_localDeviceIndex);
// Redo the channelizer stuff with the new sample rate to re-synchronize everything
m_channelizer->set(m_channelizer->getInputMessageQueue(),
m_settings.m_log2Interp,
m_settings.m_filterChainHash);
if (m_guiMessageQueue)
{
MsgSampleRateNotification *msg = MsgSampleRateNotification::create(notif.getSampleRate());
m_guiMessageQueue->push(msg);
}
return true;
}
else if (MsgConfigureLocalSource::match(cmd))
{
MsgConfigureLocalSource& cfg = (MsgConfigureLocalSource&) cmd;
qDebug() << "LocalSource::handleMessage: MsgConfigureLocalSink";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (MsgConfigureChannelizer::match(cmd))
{
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
m_settings.m_log2Interp = cfg.getLog2Interp();
m_settings.m_filterChainHash = cfg.getFilterChainHash();
qDebug() << "LocalSource::handleMessage: MsgConfigureChannelizer:"
<< " log2Interp: " << m_settings.m_log2Interp
<< " filterChainHash: " << m_settings.m_filterChainHash;
m_channelizer->set(m_channelizer->getInputMessageQueue(),
m_settings.m_log2Interp,
m_settings.m_filterChainHash);
calculateFrequencyOffset(); // This is when decimation or filter chain changes
propagateSampleRateAndFrequency(m_settings.m_localDeviceIndex);
return true;
}
else
{
return false;
}
}
QByteArray LocalSource::serialize() const
{
return m_settings.serialize();
}
bool LocalSource::deserialize(const QByteArray& data)
{
(void) data;
if (m_settings.deserialize(data))
{
MsgConfigureLocalSource *msg = MsgConfigureLocalSource::create(m_settings, true);
m_inputMessageQueue.push(msg);
return true;
}
else
{
m_settings.resetToDefaults();
MsgConfigureLocalSource *msg = MsgConfigureLocalSource::create(m_settings, true);
m_inputMessageQueue.push(msg);
return false;
}
}
void LocalSource::getLocalDevices(std::vector<uint32_t>& indexes)
{
indexes.clear();
DSPEngine *dspEngine = DSPEngine::instance();
for (uint32_t i = 0; i < dspEngine->getDeviceSinkEnginesNumber(); i++)
{
DSPDeviceSinkEngine *deviceSinkEngine = dspEngine->getDeviceSinkEngineByIndex(i);
DeviceSampleSink *deviceSink = deviceSinkEngine->getSink();
if (deviceSink->getDeviceDescription() == "LocalOutput") {
indexes.push_back(i);
}
}
}
DeviceSampleSink *LocalSource::getLocalDevice(uint32_t index)
{
DSPEngine *dspEngine = DSPEngine::instance();
if (index < dspEngine->getDeviceSinkEnginesNumber())
{
DSPDeviceSinkEngine *deviceSinkEngine = dspEngine->getDeviceSinkEngineByIndex(index);
DeviceSampleSink *deviceSink = deviceSinkEngine->getSink();
if (deviceSink->getDeviceDescription() == "LocalOutput")
{
if (!getDeviceAPI()) {
qDebug("LocalSource::getLocalDevice: the parent device is unset");
} else if (getDeviceAPI()->getDeviceUID() == deviceSinkEngine->getUID()) {
qDebug("LocalSource::getLocalDevice: sink device at index %u is the parent device", index);
} else {
return deviceSink;
}
}
else
{
qDebug("LocalSource::getLocalDevice: sink device at index %u is not a Local Output source", index);
}
}
else
{
qDebug("LocalSource::getLocalDevice: non existent sink device index: %u", index);
}
return nullptr;
}
void LocalSource::propagateSampleRateAndFrequency(uint32_t index)
{
DeviceSampleSink *deviceSink = getLocalDevice(index);
if (deviceSink)
{
deviceSink->setSampleRate(m_deviceSampleRate / (1<<m_settings.m_log2Interp));
deviceSink->setCenterFrequency(m_centerFrequency + m_frequencyOffset);
}
}
void LocalSource::applySettings(const LocalSourceSettings& settings, bool force)
{
qDebug() << "LocalSource::applySettings:"
<< " m_localDeviceIndex: " << settings.m_localDeviceIndex
<< " force: " << force;
QList<QString> reverseAPIKeys;
if ((settings.m_localDeviceIndex != m_settings.m_localDeviceIndex) || force)
{
reverseAPIKeys.append("localDeviceIndex");
DeviceSampleSink *deviceSink = getLocalDevice(settings.m_localDeviceIndex);
if (deviceSink)
{
if (m_sinkThread) {
m_sinkThread->setSampleFifo(deviceSink->getSampleFifo());
}
propagateSampleRateAndFrequency(settings.m_localDeviceIndex);
}
else
{
qWarning("LocalSource::applySettings: invalid local device for index %u", settings.m_localDeviceIndex);
}
}
if ((settings.m_useReverseAPI) && (reverseAPIKeys.size() != 0))
{
bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) ||
(m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) ||
(m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) ||
(m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex) ||
(m_settings.m_reverseAPIChannelIndex != settings.m_reverseAPIChannelIndex);
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
}
m_settings = settings;
}
void LocalSource::validateFilterChainHash(LocalSourceSettings& settings)
{
unsigned int s = 1;
for (unsigned int i = 0; i < settings.m_log2Interp; i++) {
s *= 3;
}
settings.m_filterChainHash = settings.m_filterChainHash >= s ? s-1 : settings.m_filterChainHash;
}
void LocalSource::calculateFrequencyOffset()
{
double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Interp, m_settings.m_filterChainHash);
m_frequencyOffset = m_deviceSampleRate * shiftFactor;
}
int LocalSource::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setLocalSinkSettings(new SWGSDRangel::SWGLocalSinkSettings());
response.getLocalSinkSettings()->init();
webapiFormatChannelSettings(response, m_settings);
return 200;
}
int LocalSource::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
LocalSourceSettings settings = m_settings;
if (channelSettingsKeys.contains("localDeviceIndex")) {
settings.m_localDeviceIndex = response.getLocalSourceSettings()->getLocalDeviceIndex();
}
if (channelSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getLocalSourceSettings()->getRgbColor();
}
if (channelSettingsKeys.contains("title")) {
settings.m_title = *response.getLocalSourceSettings()->getTitle();
}
if (channelSettingsKeys.contains("log2Interp")) {
settings.m_log2Interp = response.getLocalSourceSettings()->getLog2Interp();
}
if (channelSettingsKeys.contains("filterChainHash"))
{
settings.m_filterChainHash = response.getLocalSourceSettings()->getFilterChainHash();
validateFilterChainHash(settings);
}
if (channelSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getLocalSourceSettings()->getUseReverseApi() != 0;
}
if (channelSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getLocalSourceSettings()->getReverseApiAddress();
}
if (channelSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getLocalSourceSettings()->getReverseApiPort();
}
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getLocalSourceSettings()->getReverseApiDeviceIndex();
}
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIChannelIndex = response.getLocalSourceSettings()->getReverseApiChannelIndex();
}
MsgConfigureLocalSource *msg = MsgConfigureLocalSource::create(settings, force);
m_inputMessageQueue.push(msg);
if ((settings.m_log2Interp != m_settings.m_log2Interp) || (settings.m_filterChainHash != m_settings.m_filterChainHash) || force)
{
MsgConfigureChannelizer *msg = MsgConfigureChannelizer::create(settings.m_log2Interp, settings.m_filterChainHash);
m_inputMessageQueue.push(msg);
}
qDebug("LocalSource::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureLocalSource *msgToGUI = MsgConfigureLocalSource::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatChannelSettings(response, settings);
return 200;
}
void LocalSource::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const LocalSourceSettings& settings)
{
response.getLocalSourceSettings()->setLocalDeviceIndex(settings.m_localDeviceIndex);
response.getLocalSourceSettings()->setRgbColor(settings.m_rgbColor);
if (response.getLocalSourceSettings()->getTitle()) {
*response.getLocalSourceSettings()->getTitle() = settings.m_title;
} else {
response.getLocalSourceSettings()->setTitle(new QString(settings.m_title));
}
response.getLocalSourceSettings()->setLog2Interp(settings.m_log2Interp);
response.getLocalSourceSettings()->setFilterChainHash(settings.m_filterChainHash);
response.getLocalSourceSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getLocalSourceSettings()->getReverseApiAddress()) {
*response.getLocalSourceSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getLocalSourceSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getLocalSourceSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getLocalSourceSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
response.getLocalSourceSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
}
void LocalSource::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSourceSettings& settings, bool force)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
swgChannelSettings->setDirection(1); // single source (Tx)
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
swgChannelSettings->setChannelType(new QString("LocalSource"));
swgChannelSettings->setLocalSourceSettings(new SWGSDRangel::SWGLocalSourceSettings());
SWGSDRangel::SWGLocalSourceSettings *swgLocalSourceSettings = swgChannelSettings->getLocalSourceSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (channelSettingsKeys.contains("localDeviceIndex") || force) {
swgLocalSourceSettings->setLocalDeviceIndex(settings.m_localDeviceIndex);
}
if (channelSettingsKeys.contains("rgbColor") || force) {
swgLocalSourceSettings->setRgbColor(settings.m_rgbColor);
}
if (channelSettingsKeys.contains("title") || force) {
swgLocalSourceSettings->setTitle(new QString(settings.m_title));
}
if (channelSettingsKeys.contains("log2Interp") || force) {
swgLocalSourceSettings->setLog2Interp(settings.m_log2Interp);
}
if (channelSettingsKeys.contains("filterChainHash") || force) {
swgLocalSourceSettings->setFilterChainHash(settings.m_filterChainHash);
}
QString channelSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/channel/%4/settings")
.arg(settings.m_reverseAPIAddress)
.arg(settings.m_reverseAPIPort)
.arg(settings.m_reverseAPIDeviceIndex)
.arg(settings.m_reverseAPIChannelIndex);
m_networkRequest.setUrl(QUrl(channelSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer=new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgChannelSettings->asJson().toUtf8());
buffer->seek(0);
// Always use PATCH to avoid passing reverse API settings
m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
delete swgChannelSettings;
}
void LocalSource::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "LocalSource::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
return;
}
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("LocalSource::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}

Wyświetl plik

@ -0,0 +1,193 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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_LOCALSOURCE_H_
#define INCLUDE_LOCALSOURCE_H_
#include <QObject>
#include <QMutex>
#include <QNetworkRequest>
#include "dsp/basebandsamplesource.h"
#include "util/message.h"
#include "channel/channelapi.h"
#include "localsourcesettings.h"
class DeviceAPI;
class DeviceSampleSink;
class ThreadedBasebandSampleSource;
class UpChannelizer;
class LocalSourceThread;
class QNetworkAccessManager;
class QNetworkReply;
class LocalSource : public BasebandSampleSource, public ChannelAPI {
Q_OBJECT
public:
class MsgConfigureLocalSource : public Message {
MESSAGE_CLASS_DECLARATION
public:
const LocalSourceSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureLocalSource* create(const LocalSourceSettings& settings, bool force)
{
return new MsgConfigureLocalSource(settings, force);
}
private:
LocalSourceSettings m_settings;
bool m_force;
MsgConfigureLocalSource(const LocalSourceSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgSampleRateNotification : public Message {
MESSAGE_CLASS_DECLARATION
public:
static MsgSampleRateNotification* create(int sampleRate) {
return new MsgSampleRateNotification(sampleRate);
}
int getSampleRate() const { return m_sampleRate; }
private:
MsgSampleRateNotification(int sampleRate) :
Message(),
m_sampleRate(sampleRate)
{ }
int m_sampleRate;
};
class MsgConfigureChannelizer : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getLog2Interp() const { return m_log2Interp; }
int getFilterChainHash() const { return m_filterChainHash; }
static MsgConfigureChannelizer* create(unsigned int m_log2Interp, unsigned int m_filterChainHash) {
return new MsgConfigureChannelizer(m_log2Interp, m_filterChainHash);
}
private:
unsigned int m_log2Interp;
unsigned int m_filterChainHash;
MsgConfigureChannelizer(unsigned int log2Interp, unsigned int filterChainHash) :
Message(),
m_log2Interp(log2Interp),
m_filterChainHash(filterChainHash)
{ }
};
LocalSource(DeviceAPI *deviceAPI);
virtual ~LocalSource();
virtual void destroy() { delete this; }
virtual void pull(Sample& sample);
virtual void pullAudio(int nbSamples);
virtual void start();
virtual void stop();
virtual bool handleMessage(const Message& cmd);
virtual void getIdentifier(QString& id) { id = objectName(); }
virtual void getTitle(QString& title) { title = "Local Sink"; }
virtual qint64 getCenterFrequency() const { return m_frequencyOffset; }
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual int getNbSinkStreams() const { return 0; }
virtual int getNbSourceStreams() const { return 1; }
virtual qint64 getStreamCenterFrequency(int streamIndex, bool sinkElseSource) const
{
(void) streamIndex;
(void) sinkElseSource;
return m_frequencyOffset;
}
virtual int webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage);
/** Set center frequency given in Hz */
void setCenterFrequency(uint64_t centerFrequency) { m_centerFrequency = centerFrequency; }
/** Set sample rate given in Hz */
void setSampleRate(uint32_t sampleRate) { m_sampleRate = sampleRate; }
void setChannelizer(unsigned int log2Interp, unsigned int filterChainHash);
void getLocalDevices(std::vector<uint32_t>& indexes);
static const QString m_channelIdURI;
static const QString m_channelId;
signals:
void pullSamples(unsigned int count);
private:
DeviceAPI *m_deviceAPI;
ThreadedBasebandSampleSource* m_threadedChannelizer;
UpChannelizer* m_channelizer;
bool m_running;
LocalSourceSettings m_settings;
LocalSourceThread *m_sinkThread;
SampleSourceFifo *m_localSampleSourceFifo;
int m_chunkSize;
SampleVector m_localSamples;
int m_localSamplesIndex;
int m_localSamplesIndexOffset;
uint64_t m_centerFrequency;
int64_t m_frequencyOffset;
uint32_t m_sampleRate;
uint32_t m_deviceSampleRate;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void applySettings(const LocalSourceSettings& settings, bool force = false);
DeviceSampleSink *getLocalDevice(uint32_t index);
void propagateSampleRateAndFrequency(uint32_t index);
void validateFilterChainHash(LocalSourceSettings& settings);
void calculateFrequencyOffset();
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const LocalSourceSettings& settings);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSourceSettings& settings, bool force);
private slots:
void networkManagerFinished(QNetworkReply *reply);
void processSamples(unsigned int offset);
};
#endif /* INCLUDE_LOCALSOURCE_H_ */

Wyświetl plik

@ -0,0 +1,337 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 <QLocale>
#include "device/deviceuiset.h"
#include "gui/basicchannelsettingsdialog.h"
#include "dsp/hbfilterchainconverter.h"
#include "mainwindow.h"
#include "localsourcegui.h"
#include "localsource.h"
#include "ui_localsourcegui.h"
LocalSourceGUI* LocalSourceGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channelTx)
{
LocalSourceGUI* gui = new LocalSourceGUI(pluginAPI, deviceUISet, channelTx);
return gui;
}
void LocalSourceGUI::destroy()
{
delete this;
}
void LocalSourceGUI::setName(const QString& name)
{
setObjectName(name);
}
QString LocalSourceGUI::getName() const
{
return objectName();
}
qint64 LocalSourceGUI::getCenterFrequency() const {
return 0;
}
void LocalSourceGUI::setCenterFrequency(qint64 centerFrequency)
{
(void) centerFrequency;
}
void LocalSourceGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings(true);
}
QByteArray LocalSourceGUI::serialize() const
{
return m_settings.serialize();
}
bool LocalSourceGUI::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
applySettings(true);
return true;
} else {
resetToDefaults();
return false;
}
}
bool LocalSourceGUI::handleMessage(const Message& message)
{
if (LocalSource::MsgSampleRateNotification::match(message))
{
LocalSource::MsgSampleRateNotification& notif = (LocalSource::MsgSampleRateNotification&) message;
//m_channelMarker.setBandwidth(notif.getSampleRate());
m_sampleRate = notif.getSampleRate();
displayRateAndShift();
return true;
}
else if (LocalSource::MsgConfigureLocalSource::match(message))
{
const LocalSource::MsgConfigureLocalSource& cfg = (LocalSource::MsgConfigureLocalSource&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
else
{
return false;
}
}
LocalSourceGUI::LocalSourceGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *channeltx, QWidget* parent) :
RollupWidget(parent),
ui(new Ui::LocalSourceGUI),
m_pluginAPI(pluginAPI),
m_deviceUISet(deviceUISet),
m_sampleRate(0),
m_tickCount(0)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true);
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
m_localSource = (LocalSource*) channeltx;
m_localSource->setMessageQueueToGUI(getInputMessageQueue());
m_channelMarker.blockSignals(true);
m_channelMarker.setColor(m_settings.m_rgbColor);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle("Local Source");
m_channelMarker.blockSignals(false);
m_channelMarker.setVisible(true); // activate signal on the last setting only
m_settings.setChannelMarker(&m_channelMarker);
m_deviceUISet->registerRxChannelInstance(LocalSource::m_channelIdURI, this);
m_deviceUISet->addChannelMarker(&m_channelMarker);
m_deviceUISet->addRollupWidget(this);
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleSourceMessages()));
//connect(&(m_deviceUISet->m_deviceSourceAPI->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick()));
m_time.start();
updateLocalDevices();
displaySettings();
applySettings(true);
}
LocalSourceGUI::~LocalSourceGUI()
{
m_deviceUISet->removeTxChannelInstance(this);
delete m_localSource; // TODO: check this: when the GUI closes it has to delete the demodulator
delete ui;
}
void LocalSourceGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void LocalSourceGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
setTitleColor(m_channelMarker.getColor());
LocalSource::MsgConfigureLocalSource* message = LocalSource::MsgConfigureLocalSource::create(m_settings, force);
m_localSource->getInputMessageQueue()->push(message);
}
}
void LocalSourceGUI::applyChannelSettings()
{
if (m_doApplySettings)
{
LocalSource::MsgConfigureChannelizer *msgChan = LocalSource::MsgConfigureChannelizer::create(
m_settings.m_log2Interp,
m_settings.m_filterChainHash);
m_localSource->getInputMessageQueue()->push(msgChan);
}
}
void LocalSourceGUI::displaySettings()
{
m_channelMarker.blockSignals(true);
m_channelMarker.setCenterFrequency(0);
m_channelMarker.setTitle(m_settings.m_title);
m_channelMarker.setBandwidth(m_sampleRate); // TODO
m_channelMarker.setMovable(false); // do not let user move the center arbitrarily
m_channelMarker.blockSignals(false);
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
setTitleColor(m_settings.m_rgbColor);
setWindowTitle(m_channelMarker.getTitle());
blockApplySettings(true);
ui->interpolationFactor->setCurrentIndex(m_settings.m_log2Interp);
applyInterpolation();
blockApplySettings(false);
}
void LocalSourceGUI::displayRateAndShift()
{
int shift = m_shiftFrequencyFactor * m_sampleRate;
double channelSampleRate = ((double) m_sampleRate) / (1<<m_settings.m_log2Interp);
QLocale loc;
ui->offsetFrequencyText->setText(tr("%1 Hz").arg(loc.toString(shift)));
ui->channelRateText->setText(tr("%1k").arg(QString::number(channelSampleRate / 1000.0, 'g', 5)));
m_channelMarker.setCenterFrequency(shift);
m_channelMarker.setBandwidth(channelSampleRate);
}
void LocalSourceGUI::updateLocalDevices()
{
std::vector<uint32_t> localDevicesIndexes;
m_localSource->getLocalDevices(localDevicesIndexes);
ui->localDevice->clear();
std::vector<uint32_t>::const_iterator it = localDevicesIndexes.begin();
for (; it != localDevicesIndexes.end(); ++it) {
ui->localDevice->addItem(tr("%1").arg(*it), QVariant(*it));
}
}
void LocalSourceGUI::leaveEvent(QEvent*)
{
m_channelMarker.setHighlighted(false);
}
void LocalSourceGUI::enterEvent(QEvent*)
{
m_channelMarker.setHighlighted(true);
}
void LocalSourceGUI::handleSourceMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
void LocalSourceGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
}
void LocalSourceGUI::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.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);
setTitleColor(m_settings.m_rgbColor);
applySettings();
}
resetContextMenuType();
}
void LocalSourceGUI::on_interpolationFactor_currentIndexChanged(int index)
{
m_settings.m_log2Interp = index;
applyInterpolation();
}
void LocalSourceGUI::on_position_valueChanged(int value)
{
m_settings.m_filterChainHash = value;
applyPosition();
}
void LocalSourceGUI::on_localDevice_currentIndexChanged(int index)
{
m_settings.m_localDeviceIndex = ui->localDevice->itemData(index).toInt();
applySettings();
}
void LocalSourceGUI::on_localDevicesRefresh_clicked(bool checked)
{
(void) checked;
updateLocalDevices();
}
void LocalSourceGUI::applyInterpolation()
{
uint32_t maxHash = 1;
for (uint32_t i = 0; i < m_settings.m_log2Interp; i++) {
maxHash *= 3;
}
ui->position->setMaximum(maxHash-1);
ui->position->setValue(m_settings.m_filterChainHash);
m_settings.m_filterChainHash = ui->position->value();
applyPosition();
}
void LocalSourceGUI::applyPosition()
{
ui->filterChainIndex->setText(tr("%1").arg(m_settings.m_filterChainHash));
QString s;
m_shiftFrequencyFactor = HBFilterChainConverter::convertToString(m_settings.m_log2Interp, m_settings.m_filterChainHash, s);
ui->filterChainText->setText(s);
displayRateAndShift();
applyChannelSettings();
}
void LocalSourceGUI::tick()
{
if (++m_tickCount == 20) { // once per second
m_tickCount = 0;
}
}

Wyświetl plik

@ -0,0 +1,105 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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_LOCALSOURCE_LOCALSOURCEGUI_H_
#define PLUGINS_CHANNELTX_LOCALSOURCE_LOCALSOURCEGUI_H_
#include <stdint.h>
#include <QObject>
#include <QTime>
#include "plugin/plugininstancegui.h"
#include "dsp/channelmarker.h"
#include "gui/rollupwidget.h"
#include "util/messagequeue.h"
#include "localsourcesettings.h"
class PluginAPI;
class DeviceUISet;
class LocalSource;
class BasebandSampleSource;
namespace Ui {
class LocalSourceGUI;
}
class LocalSourceGUI : public RollupWidget, public PluginInstanceGUI {
Q_OBJECT
public:
static LocalSourceGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *txChannel);
virtual void destroy();
void setName(const QString& name);
QString getName() const;
virtual qint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual bool handleMessage(const Message& message);
private:
Ui::LocalSourceGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
ChannelMarker m_channelMarker;
LocalSourceSettings m_settings;
int m_sampleRate;
quint64 m_deviceCenterFrequency; //!< Center frequency in device
double m_shiftFrequencyFactor; //!< Channel frequency shift factor
bool m_doApplySettings;
LocalSource* m_localSource;
MessageQueue m_inputMessageQueue;
QTime m_time;
uint32_t m_tickCount;
explicit LocalSourceGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSource *txChannel, QWidget* parent = 0);
virtual ~LocalSourceGUI();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void applyChannelSettings();
void displaySettings();
void displayRateAndShift();
void updateLocalDevices();
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
void applyInterpolation();
void applyPosition();
private slots:
void handleSourceMessages();
void on_interpolationFactor_currentIndexChanged(int index);
void on_position_valueChanged(int value);
void on_localDevice_currentIndexChanged(int index);
void on_localDevicesRefresh_clicked(bool checked);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void tick();
};
#endif /* PLUGINS_CHANNELRX_LOCALSINK_LOCALSINKGUI_H_ */

Wyświetl plik

@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LocalSourceGUI</class>
<widget class="RollupWidget" name="LocalSourceGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>110</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>320</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Local Source</string>
</property>
<property name="statusTip">
<string>Local Source</string>
</property>
<widget class="QWidget" name="settingsContainer" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>301</width>
<height>91</height>
</rect>
</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="QVBoxLayout" name="decimationLayer">
<property name="spacing">
<number>3</number>
</property>
<item>
<layout class="QHBoxLayout" name="decimationStageLayer">
<item>
<widget class="QLabel" name="interpolationLabel">
<property name="text">
<string>Int</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="interpolationFactor">
<property name="maximumSize">
<size>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Decimation factor</string>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>8</string>
</property>
</item>
<item>
<property name="text">
<string>16</string>
</property>
</item>
<item>
<property name="text">
<string>32</string>
</property>
</item>
<item>
<property name="text">
<string>64</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="channelRateText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Effective channel rate (kS/s)</string>
</property>
<property name="text">
<string>0000k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterChainText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter chain stages left to right (L: low, C: center, H: high) </string>
</property>
<property name="text">
<string>LLLLLL</string>
</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="QLabel" name="offsetFrequencyText">
<property name="minimumSize">
<size>
<width>85</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Offset frequency with thousands separator (Hz)</string>
</property>
<property name="text">
<string>-9,999,999 Hz</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="decimationShiftLayer">
<property name="rightMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="positionLabel">
<property name="text">
<string>Pos</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="position">
<property name="toolTip">
<string>Center frequency position</string>
</property>
<property name="maximum">
<number>2</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="filterChainIndex">
<property name="minimumSize">
<size>
<width>24</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Filter chain hash code</string>
</property>
<property name="text">
<string>000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="localDeviceLayout">
<item>
<widget class="QLabel" name="localDeviceLabel">
<property name="text">
<string>Device</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="localDevice">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Local device deviceset index</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="localDevicesRefresh">
<property name="maximumSize">
<size>
<width>24</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Refresh indexes of available local devices</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/recycle.png</normaloff>:/recycle.png</iconset>
</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>
</layout>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>RollupWidget</class>
<extends>QWidget</extends>
<header>gui/rollupwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

Wyświetl plik

@ -0,0 +1,78 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "localsourceplugin.h"
#include <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "localsourcegui.h"
#endif
#include "localsource.h"
const PluginDescriptor LocalSourcePlugin::m_pluginDescriptor = {
QString("Local channel source"),
QString("4.8.0"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
QString("https://github.com/f4exb/sdrangel")
};
LocalSourcePlugin::LocalSourcePlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(0)
{
}
const PluginDescriptor& LocalSourcePlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void LocalSourcePlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register channel Source
m_pluginAPI->registerTxChannel(LocalSource::m_channelIdURI, LocalSource::m_channelId, this);
}
#ifdef SERVER_MODE
PluginInstanceGUI* LocalSourcePlugin::createTxChannelGUI(
DeviceUISet *deviceUISet __attribute__((unused)),
BasebandSampleSource *txChannel __attribute__((unused)))
{
return 0;
}
#else
PluginInstanceGUI* LocalSourcePlugin::createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel)
{
return LocalSourceGUI::create(m_pluginAPI, deviceUISet, txChannel);
}
#endif
BasebandSampleSource* LocalSourcePlugin::createTxChannelBS(DeviceAPI *deviceAPI)
{
return new LocalSource(deviceAPI);
}
ChannelAPI* LocalSourcePlugin::createTxChannelCS(DeviceAPI *deviceAPI)
{
return new LocalSource(deviceAPI);
}

Wyświetl plik

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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_LOCALSOURCE_LOCALSOURCEPLUGIN_H_
#define PLUGINS_CHANNELTX_LOCALSOURCE_LOCALSOURCEPLUGIN_H_
#include <QObject>
#include "plugin/plugininterface.h"
class DeviceUISet;
class BasebandSampleSource;
class LocalSourcePlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.demod.localsource")
public:
explicit LocalSourcePlugin(QObject* parent = 0);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual PluginInstanceGUI* createTxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSource *txChannel);
virtual BasebandSampleSource* createTxChannelBS(DeviceAPI *deviceAPI);
virtual ChannelAPI* createTxChannelCS(DeviceAPI *deviceAPI);
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif /* PLUGINS_CHANNELTX_LOCALSOURCE_LOCALSOURCEPLUGIN_H_ */

Wyświetl plik

@ -0,0 +1,111 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "localsourcesettings.h"
#include <QColor>
#include "util/simpleserializer.h"
#include "settings/serializable.h"
LocalSourceSettings::LocalSourceSettings()
{
resetToDefaults();
}
void LocalSourceSettings::resetToDefaults()
{
m_localDeviceIndex = 0;
m_rgbColor = QColor(140, 4, 4).rgb();
m_title = "Local sink";
m_log2Interp = 0;
m_filterChainHash = 0;
m_channelMarker = nullptr;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
m_reverseAPIChannelIndex = 0;
}
QByteArray LocalSourceSettings::serialize() const
{
SimpleSerializer s(1);
s.writeU32(1, m_localDeviceIndex);
s.writeU32(5, m_rgbColor);
s.writeString(6, m_title);
s.writeBool(7, m_useReverseAPI);
s.writeString(8, m_reverseAPIAddress);
s.writeU32(9, m_reverseAPIPort);
s.writeU32(10, m_reverseAPIDeviceIndex);
s.writeU32(11, m_reverseAPIChannelIndex);
s.writeU32(12, m_log2Interp);
s.writeU32(13, m_filterChainHash);
return s.final();
}
bool LocalSourceSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid())
{
resetToDefaults();
return false;
}
if(d.getVersion() == 1)
{
uint32_t tmp;
QString strtmp;
d.readU32(1, &m_localDeviceIndex, 0);
d.readU32(5, &m_rgbColor, QColor(0, 255, 255).rgb());
d.readString(6, &m_title, "Local sink");
d.readBool(7, &m_useReverseAPI, false);
d.readString(8, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(9, &tmp, 0);
if ((tmp > 1023) && (tmp < 65535)) {
m_reverseAPIPort = tmp;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(10, &tmp, 0);
m_reverseAPIDeviceIndex = tmp > 99 ? 99 : tmp;
d.readU32(11, &tmp, 0);
m_reverseAPIChannelIndex = tmp > 99 ? 99 : tmp;
d.readU32(12, &tmp, 0);
m_log2Interp = tmp > 6 ? 6 : tmp;
d.readU32(13, &m_filterChainHash, 0);
return true;
}
else
{
resetToDefaults();
return false;
}
}

Wyświetl plik

@ -0,0 +1,48 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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_LOCALSOURCESETTINGS_H_
#define INCLUDE_LOCALSOURCESETTINGS_H_
#include <QByteArray>
#include <QString>
class Serializable;
struct LocalSourceSettings
{
uint32_t m_localDeviceIndex;
quint32 m_rgbColor;
QString m_title;
uint32_t m_log2Interp;
uint32_t m_filterChainHash;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
uint16_t m_reverseAPIChannelIndex;
Serializable *m_channelMarker;
LocalSourceSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* INCLUDE_LOCALSOURCESETTINGS_H_ */

Wyświetl plik

@ -0,0 +1,110 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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 "dsp/samplesourcefifo.h"
#include "localsourcethread.h"
MESSAGE_CLASS_DEFINITION(LocalSourceThread::MsgStartStop, Message)
LocalSourceThread::LocalSourceThread(QObject* parent) :
QThread(parent),
m_running(false),
m_sampleFifo(0)
{
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
}
LocalSourceThread::~LocalSourceThread()
{
qDebug("LocalSourceThread::~LocalSourceThread");
}
void LocalSourceThread::startStop(bool start)
{
MsgStartStop *msg = MsgStartStop::create(start);
m_inputMessageQueue.push(msg);
}
void LocalSourceThread::setSampleFifo(SampleSourceFifo *sampleFifo)
{
m_sampleFifo = sampleFifo;
}
void LocalSourceThread::pullSamples(unsigned int count)
{
SampleVector::iterator beginRead;
m_sampleFifo->readAdvance(beginRead, count);
emit samplesAvailable(m_sampleFifo->getIteratorOffset(beginRead));
}
void LocalSourceThread::startWork()
{
qDebug("LocalSourceThread::startWork");
m_startWaitMutex.lock();
start();
while(!m_running) {
m_startWaiter.wait(&m_startWaitMutex, 100);
}
m_startWaitMutex.unlock();
}
void LocalSourceThread::stopWork()
{
qDebug("LocalSourceThread::stopWork");
m_running = false;
wait();
}
void LocalSourceThread::run()
{
qDebug("LocalSinkThread::run: begin");
m_running = true;
m_startWaiter.wakeAll();
while (m_running)
{
sleep(1); // Do nothing as everything is in the data handler (dequeuer)
}
m_running = false;
qDebug("LocalSinkThread::run: end");
}
void LocalSourceThread::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (MsgStartStop::match(*message))
{
MsgStartStop* notif = (MsgStartStop*) message;
qDebug("LocalSourceThread::handleInputMessages: MsgStartStop: %s", notif->getStartStop() ? "start" : "stop");
if (notif->getStartStop()) {
startWork();
} else {
stopWork();
}
delete message;
}
}
}

Wyświetl plik

@ -0,0 +1,83 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (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_LOCALOURCE_LOCALOURCETHREAD_H_
#define PLUGINS_CHANNELTX_LOCALOURCE_LOCALOURCETHREAD_H_
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include "dsp/dsptypes.h"
#include "util/message.h"
#include "util/messagequeue.h"
class SampleSourceFifo;
class LocalSourceThread : public QThread {
Q_OBJECT
public:
class MsgStartStop : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getStartStop() const { return m_startStop; }
static MsgStartStop* create(bool startStop) {
return new MsgStartStop(startStop);
}
protected:
bool m_startStop;
MsgStartStop(bool startStop) :
Message(),
m_startStop(startStop)
{ }
};
LocalSourceThread(QObject* parent = 0);
~LocalSourceThread();
void startStop(bool start);
void setSampleFifo(SampleSourceFifo *sampleFifo);
public slots:
void pullSamples(unsigned int count);
signals:
void samplesAvailable(int offset);
private:
QMutex m_startWaitMutex;
QWaitCondition m_startWaiter;
volatile bool m_running;
SampleSourceFifo *m_sampleFifo;
MessageQueue m_inputMessageQueue;
void startWork();
void stopWork();
void run();
private slots:
void handleInputMessages();
};
#endif // PLUGINS_CHANNELTX_LOCALSINK_LOCALSINKTHREAD_H_

Wyświetl plik

@ -92,3 +92,13 @@ void SampleSourceFifo::bumpIndex(SampleVector::iterator& writeAt)
writeAt = m_data.begin() + m_iw;
}
int SampleSourceFifo::getIteratorOffset(const SampleVector::iterator& iterator)
{
return iterator - m_data.begin();
}
void SampleSourceFifo::setIteratorFromOffset(SampleVector::iterator& iterator, int offset)
{
iterator = m_data.begin() + offset;
}

Wyświetl plik

@ -41,6 +41,8 @@ public:
void getReadIterator(SampleVector::iterator& readUntil); //!< get iterator past the last sample of a read advance operation (i.e. current read iterator)
void getWriteIterator(SampleVector::iterator& writeAt); //!< get iterator to current item for update - write phase 1
void bumpIndex(SampleVector::iterator& writeAt); //!< copy current item to second buffer and bump write index - write phase 2
int getIteratorOffset(const SampleVector::iterator& iterator);
void setIteratorFromOffset(SampleVector::iterator& iterator, int offset);
void write(const Sample& sample); //!< write directly - phase 1 + phase 2

Wyświetl plik

@ -0,0 +1,25 @@
LocalSourceSettings:
description: "Local channel source settings"
properties:
localDeviceIndex:
description: "Sending local device index"
type: integer
rgbColor:
type: integer
title:
type: string
log2Interp:
type: integer
filterChainHash:
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

Wyświetl plik

@ -0,0 +1,25 @@
LocalSourceSettings:
description: "Local channel source settings"
properties:
localDeviceIndex:
description: "Sending local device index"
type: integer
rgbColor:
type: integer
title:
type: string
log2Interp:
type: integer
filterChainHash:
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

Wyświetl plik

@ -0,0 +1,299 @@
/**
* 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: 4.8.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 "SWGLocalSourceSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGLocalSourceSettings::SWGLocalSourceSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGLocalSourceSettings::SWGLocalSourceSettings() {
local_device_index = 0;
m_local_device_index_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = nullptr;
m_title_isSet = false;
log2_interp = 0;
m_log2_interp_isSet = false;
filter_chain_hash = 0;
m_filter_chain_hash_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;
}
SWGLocalSourceSettings::~SWGLocalSourceSettings() {
this->cleanup();
}
void
SWGLocalSourceSettings::init() {
local_device_index = 0;
m_local_device_index_isSet = false;
rgb_color = 0;
m_rgb_color_isSet = false;
title = new QString("");
m_title_isSet = false;
log2_interp = 0;
m_log2_interp_isSet = false;
filter_chain_hash = 0;
m_filter_chain_hash_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;
}
void
SWGLocalSourceSettings::cleanup() {
if(title != nullptr) {
delete title;
}
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGLocalSourceSettings*
SWGLocalSourceSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGLocalSourceSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&local_device_index, pJson["localDeviceIndex"], "qint32", "");
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
::SWGSDRangel::setValue(&log2_interp, pJson["log2Interp"], "qint32", "");
::SWGSDRangel::setValue(&filter_chain_hash, pJson["filterChainHash"], "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", "");
}
QString
SWGLocalSourceSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGLocalSourceSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_local_device_index_isSet){
obj->insert("localDeviceIndex", QJsonValue(local_device_index));
}
if(m_rgb_color_isSet){
obj->insert("rgbColor", QJsonValue(rgb_color));
}
if(title != nullptr && *title != QString("")){
toJsonValue(QString("title"), title, obj, QString("QString"));
}
if(m_log2_interp_isSet){
obj->insert("log2Interp", QJsonValue(log2_interp));
}
if(m_filter_chain_hash_isSet){
obj->insert("filterChainHash", QJsonValue(filter_chain_hash));
}
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));
}
return obj;
}
qint32
SWGLocalSourceSettings::getLocalDeviceIndex() {
return local_device_index;
}
void
SWGLocalSourceSettings::setLocalDeviceIndex(qint32 local_device_index) {
this->local_device_index = local_device_index;
this->m_local_device_index_isSet = true;
}
qint32
SWGLocalSourceSettings::getRgbColor() {
return rgb_color;
}
void
SWGLocalSourceSettings::setRgbColor(qint32 rgb_color) {
this->rgb_color = rgb_color;
this->m_rgb_color_isSet = true;
}
QString*
SWGLocalSourceSettings::getTitle() {
return title;
}
void
SWGLocalSourceSettings::setTitle(QString* title) {
this->title = title;
this->m_title_isSet = true;
}
qint32
SWGLocalSourceSettings::getLog2Interp() {
return log2_interp;
}
void
SWGLocalSourceSettings::setLog2Interp(qint32 log2_interp) {
this->log2_interp = log2_interp;
this->m_log2_interp_isSet = true;
}
qint32
SWGLocalSourceSettings::getFilterChainHash() {
return filter_chain_hash;
}
void
SWGLocalSourceSettings::setFilterChainHash(qint32 filter_chain_hash) {
this->filter_chain_hash = filter_chain_hash;
this->m_filter_chain_hash_isSet = true;
}
qint32
SWGLocalSourceSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGLocalSourceSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGLocalSourceSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGLocalSourceSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGLocalSourceSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGLocalSourceSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGLocalSourceSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGLocalSourceSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
qint32
SWGLocalSourceSettings::getReverseApiChannelIndex() {
return reverse_api_channel_index;
}
void
SWGLocalSourceSettings::setReverseApiChannelIndex(qint32 reverse_api_channel_index) {
this->reverse_api_channel_index = reverse_api_channel_index;
this->m_reverse_api_channel_index_isSet = true;
}
bool
SWGLocalSourceSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_local_device_index_isSet){ isObjectUpdated = true; break;}
if(m_rgb_color_isSet){ isObjectUpdated = true; break;}
if(title != nullptr && *title != QString("")){ isObjectUpdated = true; break;}
if(m_log2_interp_isSet){ isObjectUpdated = true; break;}
if(m_filter_chain_hash_isSet){ isObjectUpdated = true; break;}
if(m_use_reverse_api_isSet){ isObjectUpdated = true; break;}
if(reverse_api_address != nullptr && *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;}
}while(false);
return isObjectUpdated;
}
}

Wyświetl plik

@ -0,0 +1,113 @@
/**
* 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: 4.8.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.
*/
/*
* SWGLocalSourceSettings.h
*
* Local channel source settings
*/
#ifndef SWGLocalSourceSettings_H_
#define SWGLocalSourceSettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGLocalSourceSettings: public SWGObject {
public:
SWGLocalSourceSettings();
SWGLocalSourceSettings(QString* json);
virtual ~SWGLocalSourceSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGLocalSourceSettings* fromJson(QString &jsonString) override;
qint32 getLocalDeviceIndex();
void setLocalDeviceIndex(qint32 local_device_index);
qint32 getRgbColor();
void setRgbColor(qint32 rgb_color);
QString* getTitle();
void setTitle(QString* title);
qint32 getLog2Interp();
void setLog2Interp(qint32 log2_interp);
qint32 getFilterChainHash();
void setFilterChainHash(qint32 filter_chain_hash);
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);
virtual bool isSet() override;
private:
qint32 local_device_index;
bool m_local_device_index_isSet;
qint32 rgb_color;
bool m_rgb_color_isSet;
QString* title;
bool m_title_isSet;
qint32 log2_interp;
bool m_log2_interp_isSet;
qint32 filter_chain_hash;
bool m_filter_chain_hash_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;
};
}
#endif /* SWGLocalSourceSettings_H_ */