New plugin pair LocalSink and LocalInput to pipe streams internally

pull/340/head
f4exb 2019-05-02 04:02:40 +02:00
rodzic 84dc7e0bb0
commit 9e5003eab9
333 zmienionych plików z 5869 dodań i 267 usunięć

Wyświetl plik

@ -27,7 +27,7 @@
#include "mainwindow.h"
#include "dsp/dsptypes.h"
#ifdef _MSC_VER
#define GIT_COMMIT_HASH_STR "v4.5.6"
#define GIT_COMMIT_HASH_STR "v4.6.0"
#else
#include "sdrangel_version.h"
#endif

6
debian/changelog vendored
Wyświetl plik

@ -1,3 +1,9 @@
sdrangel (4.6.0-1) unstable; urgency=medium
* New LocalSink and LocalInput plugin pair to use sub basebands internally
-- Edouard Griffiths, F4EXB <f4exb06@gmail.com> Thu, 02 May 2019 11:14:18 +0100
sdrangel (4.5.6-1) unstable; urgency=medium
* Remote channel sink: implemented decimation with possible center shift. Issue #331

Wyświetl plik

@ -9,6 +9,7 @@ add_subdirectory(udpsink)
add_subdirectory(demodwfm)
add_subdirectory(chanalyzer)
add_subdirectory(demodatv)
add_subdirectory(localsink)
if(LIBDSDCC_FOUND AND LIBMBE_FOUND)
add_subdirectory(demoddsd)

Wyświetl plik

@ -0,0 +1,70 @@
project(localsink)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(localsink_SOURCES
localsink.cpp
localsinkgui.cpp
localsinksettings.cpp
localsinkthread.cpp
localsinkplugin.cpp
)
set(localsink_HEADERS
localsink.h
localsinkgui.h
localsinksettings.h
localsinkthread.h
localsinkplugin.h
)
set(localsink_FORMS
localsinkgui.ui
)
#include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
qt5_wrap_ui(localsink_FORMS_HEADERS ${localsink_FORMS})
add_library(localsink SHARED
${localsink_SOURCES}
${localsink_HEADERS_MOC}
${localsink_FORMS_HEADERS}
)
if (BUILD_DEBIAN)
target_include_directories(localsink PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
else (BUILD_DEBIAN)
target_include_directories(localsink PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
endif (BUILD_DEBIAN)
if (BUILD_DEBIAN)
target_link_libraries(localsink
${QT_LIBRARIES}
sdrbase
sdrgui
swagger
)
else (BUILD_DEBIAN)
target_link_libraries(localsink
${QT_LIBRARIES}
sdrbase
sdrgui
swagger
)
endif (BUILD_DEBIAN)
target_link_libraries(localsink Qt5::Core Qt5::Widgets)
install(TARGETS localsink DESTINATION lib/plugins/channelrx)

Wyświetl plik

@ -0,0 +1,507 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 "localsink.h"
#include <sys/time.h>
#include <unistd.h>
#include <boost/crc.hpp>
#include <boost/cstdint.hpp>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGChannelSettings.h"
#include "util/simpleserializer.h"
#include "dsp/threadedbasebandsamplesink.h"
#include "dsp/downchannelizer.h"
#include "dsp/dspcommands.h"
#include "dsp/dspengine.h"
#include "dsp/devicesamplesource.h"
#include "dsp/hbfilterchainconverter.h"
#include "device/devicesourceapi.h"
#include "localsinkthread.h"
MESSAGE_CLASS_DEFINITION(LocalSink::MsgConfigureLocalSink, Message)
MESSAGE_CLASS_DEFINITION(LocalSink::MsgSampleRateNotification, Message)
MESSAGE_CLASS_DEFINITION(LocalSink::MsgConfigureChannelizer, Message)
const QString LocalSink::m_channelIdURI = "sdrangel.channel.localsink";
const QString LocalSink::m_channelId = "LocalSink";
LocalSink::LocalSink(DeviceSourceAPI *deviceAPI) :
ChannelSinkAPI(m_channelIdURI),
m_deviceAPI(deviceAPI),
m_running(false),
m_sinkThread(0),
m_txBlockIndex(0),
m_frameCount(0),
m_sampleIndex(0),
m_centerFrequency(0),
m_frequencyOffset(0),
m_sampleRate(48000),
m_deviceSampleRate(48000)
{
setObjectName(m_channelId);
m_channelizer = new DownChannelizer(this);
m_threadedChannelizer = new ThreadedBasebandSampleSink(m_channelizer, this);
m_deviceAPI->addThreadedSink(m_threadedChannelizer);
m_deviceAPI->addChannelAPI(this);
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
LocalSink::~LocalSink()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
m_deviceAPI->removeChannelAPI(this);
m_deviceAPI->removeThreadedSink(m_threadedChannelizer);
delete m_threadedChannelizer;
delete m_channelizer;
}
void LocalSink::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool firstOfBurst)
{
(void) firstOfBurst;
emit samplesAvailable((const quint8*) &(*begin), (end-begin)*sizeof(Sample));
}
void LocalSink::start()
{
qDebug("LocalSink::start");
if (m_running) {
stop();
}
m_sinkThread = new LocalSinkThread();
DeviceSampleSource *deviceSource = getLocalDevice(m_settings.m_localDeviceIndex);
if (deviceSource) {
m_sinkThread->setSampleFifo(deviceSource->getSampleFifo());
}
connect(this,
SIGNAL(samplesAvailable(const quint8*, uint)),
m_sinkThread,
SLOT(processSamples(const quint8*, uint)),
Qt::QueuedConnection);
m_sinkThread->startStop(true);
m_running = true;
}
void LocalSink::stop()
{
qDebug("LocalSink::stop");
if (m_sinkThread != 0)
{
m_sinkThread->startStop(false);
m_sinkThread->deleteLater();
m_sinkThread = 0;
}
m_running = false;
}
bool LocalSink::handleMessage(const Message& cmd)
{
(void) cmd;
if (DownChannelizer::MsgChannelizerNotification::match(cmd))
{
DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
qDebug() << "LocalSink::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() << "LocalSink::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_log2Decim,
m_settings.m_filterChainHash);
if (m_guiMessageQueue)
{
MsgSampleRateNotification *msg = MsgSampleRateNotification::create(notif.getSampleRate());
m_guiMessageQueue->push(msg);
}
return true;
}
else if (MsgConfigureLocalSink::match(cmd))
{
MsgConfigureLocalSink& cfg = (MsgConfigureLocalSink&) cmd;
qDebug() << "LocalSink::handleMessage: MsgConfigureLocalSink";
applySettings(cfg.getSettings(), cfg.getForce());
return true;
}
else if (MsgConfigureChannelizer::match(cmd))
{
MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd;
m_settings.m_log2Decim = cfg.getLog2Decim();
m_settings.m_filterChainHash = cfg.getFilterChainHash();
qDebug() << "LocalSink::handleMessage: MsgConfigureChannelizer:"
<< " log2Decim: " << m_settings.m_log2Decim
<< " filterChainHash: " << m_settings.m_filterChainHash;
m_channelizer->set(m_channelizer->getInputMessageQueue(),
m_settings.m_log2Decim,
m_settings.m_filterChainHash);
calculateFrequencyOffset(); // This is when decimation or filter chain changes
propagateSampleRateAndFrequency(m_settings.m_localDeviceIndex);
return true;
}
else
{
return false;
}
}
QByteArray LocalSink::serialize() const
{
return m_settings.serialize();
}
bool LocalSink::deserialize(const QByteArray& data)
{
(void) data;
if (m_settings.deserialize(data))
{
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, true);
m_inputMessageQueue.push(msg);
return true;
}
else
{
m_settings.resetToDefaults();
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(m_settings, true);
m_inputMessageQueue.push(msg);
return false;
}
}
void LocalSink::getLocalDevices(std::vector<uint32_t>& indexes)
{
indexes.clear();
DSPEngine *dspEngine = DSPEngine::instance();
for (uint32_t i = 0; i < dspEngine->getDeviceSourceEnginesNumber(); i++)
{
DSPDeviceSourceEngine *deviceSourceEngine = dspEngine->getDeviceSourceEngineByIndex(i);
DeviceSampleSource *deviceSource = deviceSourceEngine->getSource();
if (deviceSource->getDeviceDescription() == "LocalInput") {
indexes.push_back(i);
}
}
}
DeviceSampleSource *LocalSink::getLocalDevice(uint32_t index)
{
DSPEngine *dspEngine = DSPEngine::instance();
if (index < dspEngine->getDeviceSourceEnginesNumber())
{
DSPDeviceSourceEngine *deviceSourceEngine = dspEngine->getDeviceSourceEngineByIndex(index);
DeviceSampleSource *deviceSource = deviceSourceEngine->getSource();
if (deviceSource->getDeviceDescription() == "LocalInput")
{
if (!getDeviceSourceAPI()) {
qDebug("LocalSink::getLocalDevice: the parent device is unset");
} else if (getDeviceSourceAPI()->getDeviceUID() == deviceSourceEngine->getUID()) {
qDebug("LocalSink::getLocalDevice: source device at index %u is the parent device", index);
} else {
return deviceSource;
}
}
else
{
qDebug("LocalSink::getLocalDevice: source device at index %u is not a Local Input source", index);
}
}
else
{
qDebug("LocalSink::getLocalDevice: non existent source device index: %u", index);
}
return nullptr;
}
void LocalSink::propagateSampleRateAndFrequency(uint32_t index)
{
DeviceSampleSource *deviceSource = getLocalDevice(index);
if (deviceSource)
{
deviceSource->setSampleRate(m_deviceSampleRate / (1<<m_settings.m_log2Decim));
deviceSource->setCenterFrequency(m_centerFrequency + m_frequencyOffset);
}
}
void LocalSink::applySettings(const LocalSinkSettings& settings, bool force)
{
qDebug() << "LocalSink::applySettings:"
<< " m_localDeviceIndex: " << settings.m_localDeviceIndex
<< " force: " << force;
QList<QString> reverseAPIKeys;
if ((settings.m_localDeviceIndex != m_settings.m_localDeviceIndex) || force)
{
reverseAPIKeys.append("localDeviceIndex");
DeviceSampleSource *deviceSource = getLocalDevice(settings.m_localDeviceIndex);
if (deviceSource)
{
if (m_sinkThread) {
m_sinkThread->setSampleFifo(deviceSource->getSampleFifo());
}
propagateSampleRateAndFrequency(settings.m_localDeviceIndex);
}
else
{
qWarning("LocalSink::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 LocalSink::validateFilterChainHash(LocalSinkSettings& settings)
{
unsigned int s = 1;
for (unsigned int i = 0; i < settings.m_log2Decim; i++) {
s *= 3;
}
settings.m_filterChainHash = settings.m_filterChainHash >= s ? s-1 : settings.m_filterChainHash;
}
void LocalSink::calculateFrequencyOffset()
{
double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Decim, m_settings.m_filterChainHash);
m_frequencyOffset = m_deviceSampleRate * shiftFactor;
}
int LocalSink::webapiSettingsGet(
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
webapiFormatChannelSettings(response, m_settings);
return 200;
}
int LocalSink::webapiSettingsPutPatch(
bool force,
const QStringList& channelSettingsKeys,
SWGSDRangel::SWGChannelSettings& response,
QString& errorMessage)
{
(void) errorMessage;
LocalSinkSettings settings = m_settings;
if (channelSettingsKeys.contains("localDeviceIndex")) {
settings.m_localDeviceIndex = response.getLocalSinkSettings()->getLocalDeviceIndex();
}
if (channelSettingsKeys.contains("rgbColor")) {
settings.m_rgbColor = response.getLocalSinkSettings()->getRgbColor();
}
if (channelSettingsKeys.contains("title")) {
settings.m_title = *response.getLocalSinkSettings()->getTitle();
}
if (channelSettingsKeys.contains("log2Decim")) {
settings.m_log2Decim = response.getLocalSinkSettings()->getLog2Decim();
}
if (channelSettingsKeys.contains("filterChainHash"))
{
settings.m_filterChainHash = response.getLocalSinkSettings()->getFilterChainHash();
validateFilterChainHash(settings);
}
if (channelSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getLocalSinkSettings()->getUseReverseApi() != 0;
}
if (channelSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getLocalSinkSettings()->getReverseApiAddress();
}
if (channelSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getLocalSinkSettings()->getReverseApiPort();
}
if (channelSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getLocalSinkSettings()->getReverseApiDeviceIndex();
}
if (channelSettingsKeys.contains("reverseAPIChannelIndex")) {
settings.m_reverseAPIChannelIndex = response.getLocalSinkSettings()->getReverseApiChannelIndex();
}
MsgConfigureLocalSink *msg = MsgConfigureLocalSink::create(settings, force);
m_inputMessageQueue.push(msg);
if ((settings.m_log2Decim != m_settings.m_log2Decim) || (settings.m_filterChainHash != m_settings.m_filterChainHash) || force)
{
MsgConfigureChannelizer *msg = MsgConfigureChannelizer::create(settings.m_log2Decim, settings.m_filterChainHash);
m_inputMessageQueue.push(msg);
}
qDebug("LocalSink::webapiSettingsPutPatch: forward to GUI: %p", m_guiMessageQueue);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureLocalSink *msgToGUI = MsgConfigureLocalSink::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatChannelSettings(response, settings);
return 200;
}
void LocalSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const LocalSinkSettings& settings)
{
response.getLocalSinkSettings()->setLocalDeviceIndex(settings.m_localDeviceIndex);
response.getLocalSinkSettings()->setRgbColor(settings.m_rgbColor);
if (response.getLocalSinkSettings()->getTitle()) {
*response.getLocalSinkSettings()->getTitle() = settings.m_title;
} else {
response.getLocalSinkSettings()->setTitle(new QString(settings.m_title));
}
response.getLocalSinkSettings()->setLog2Decim(settings.m_log2Decim);
response.getLocalSinkSettings()->setFilterChainHash(settings.m_filterChainHash);
response.getLocalSinkSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getLocalSinkSettings()->getReverseApiAddress()) {
*response.getLocalSinkSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getLocalSinkSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getLocalSinkSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getLocalSinkSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
response.getLocalSinkSettings()->setReverseApiChannelIndex(settings.m_reverseAPIChannelIndex);
}
void LocalSink::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force)
{
SWGSDRangel::SWGChannelSettings *swgChannelSettings = new SWGSDRangel::SWGChannelSettings();
swgChannelSettings->setTx(0);
swgChannelSettings->setOriginatorChannelIndex(getIndexInDeviceSet());
swgChannelSettings->setOriginatorDeviceSetIndex(getDeviceSetIndex());
swgChannelSettings->setChannelType(new QString("LocalSink"));
swgChannelSettings->setLocalSinkSettings(new SWGSDRangel::SWGLocalSinkSettings());
SWGSDRangel::SWGLocalSinkSettings *swgLocalSinkSettings = swgChannelSettings->getLocalSinkSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (channelSettingsKeys.contains("localDeviceIndex") || force) {
swgLocalSinkSettings->setLocalDeviceIndex(settings.m_localDeviceIndex);
}
if (channelSettingsKeys.contains("rgbColor") || force) {
swgLocalSinkSettings->setRgbColor(settings.m_rgbColor);
}
if (channelSettingsKeys.contains("title") || force) {
swgLocalSinkSettings->setTitle(new QString(settings.m_title));
}
if (channelSettingsKeys.contains("log2Decim") || force) {
swgLocalSinkSettings->setLog2Decim(settings.m_log2Decim);
}
if (channelSettingsKeys.contains("filterChainHash") || force) {
swgLocalSinkSettings->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 LocalSink::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "LocalSink::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
return;
}
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("LocalSink::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}

Wyświetl plik

@ -0,0 +1,181 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_LOCALSINK_H_
#define INCLUDE_LOCALSINK_H_
#include <QObject>
#include <QMutex>
#include <QNetworkRequest>
#include "dsp/basebandsamplesink.h"
#include "channel/channelsinkapi.h"
#include "localsinksettings.h"
class DeviceSourceAPI;
class DeviceSampleSource;
class ThreadedBasebandSampleSink;
class DownChannelizer;
class LocalSinkThread;
class QNetworkAccessManager;
class QNetworkReply;
class LocalSink : public BasebandSampleSink, public ChannelSinkAPI {
Q_OBJECT
public:
class MsgConfigureLocalSink : public Message {
MESSAGE_CLASS_DECLARATION
public:
const LocalSinkSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureLocalSink* create(const LocalSinkSettings& settings, bool force)
{
return new MsgConfigureLocalSink(settings, force);
}
private:
LocalSinkSettings m_settings;
bool m_force;
MsgConfigureLocalSink(const LocalSinkSettings& 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 getLog2Decim() const { return m_log2Decim; }
int getFilterChainHash() const { return m_filterChainHash; }
static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency)
{
return new MsgConfigureChannelizer(sampleRate, centerFrequency);
}
private:
unsigned int m_log2Decim;
unsigned int m_filterChainHash;
MsgConfigureChannelizer(unsigned int log2Decim, int filterChainHash) :
Message(),
m_log2Decim(log2Decim),
m_filterChainHash(filterChainHash)
{ }
};
LocalSink(DeviceSourceAPI *deviceAPI);
virtual ~LocalSink();
virtual void destroy() { delete this; }
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool po);
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 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 log2Decim, unsigned int filterChainHash);
void getLocalDevices(std::vector<uint32_t>& indexes);
static const QString m_channelIdURI;
static const QString m_channelId;
signals:
void samplesAvailable(const quint8* data, uint count);
private:
DeviceSourceAPI *m_deviceAPI;
ThreadedBasebandSampleSink* m_threadedChannelizer;
DownChannelizer* m_channelizer;
bool m_running;
LocalSinkSettings m_settings;
LocalSinkThread *m_sinkThread;
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
uint16_t m_frameCount; //!< transmission frame count
int m_sampleIndex; //!< Current sample index in protected block data
QMutex m_dataBlockMutex;
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 LocalSinkSettings& settings, bool force = false);
DeviceSampleSource *getLocalDevice(uint32_t index);
void propagateSampleRateAndFrequency(uint32_t index);
void validateFilterChainHash(LocalSinkSettings& settings);
void calculateFrequencyOffset();
void webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& response, const LocalSinkSettings& settings);
void webapiReverseSendSettings(QList<QString>& channelSettingsKeys, const LocalSinkSettings& settings, bool force);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif /* INCLUDE_LOCALSINK_H_ */

Wyświetl plik

@ -0,0 +1,60 @@
#--------------------------------------------------------
#
# Pro file for Windows builds with Qt Creator
#
#--------------------------------------------------------
TEMPLATE = lib
CONFIG += plugin
QT += core gui widgets multimedia network opengl
TARGET = localsink
INCLUDEPATH += $$PWD
INCLUDEPATH += ../../../exports
INCLUDEPATH += ../../../sdrbase
INCLUDEPATH += ../../../sdrgui
INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client
macx:INCLUDEPATH += /opt/local/include
DEFINES += USE_SSE2=1
QMAKE_CXXFLAGS += -msse2
DEFINES += USE_SSSE3=1
QMAKE_CXXFLAGS += -mssse3
DEFINES += USE_SSE4_1=1
QMAKE_CXXFLAGS += -msse4.1
QMAKE_CXXFLAGS += -std=c++11
CONFIG(Release):build_subdir = release
CONFIG(Debug):build_subdir = debug
CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0"
CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0"
CONFIG(macx):INCLUDEPATH += "../../../boost_1_69_0"
SOURCES += localsink.cpp\
localsinkgui.cpp\
localsinksettings.cpp\
localsinkplugin.cpp\
localsinkthread.cpp
HEADERS += localsink.h\
localsinkgui.h\
localsinksettings.h\
localsinkplugin.h\
localsinkthread.h
FORMS += localsinkgui.ui
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui
LIBS += -L../../../swagger/$${build_subdir} -lswagger
macx {
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/
}
RESOURCES = ../../../sdrgui/resources/res.qrc
CONFIG(MINGW32):DEFINES += USE_INTERNAL_TIMER=1

Wyświetl plik

@ -0,0 +1,333 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 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/devicesourceapi.h"
#include "device/deviceuiset.h"
#include "gui/basicchannelsettingsdialog.h"
#include "dsp/hbfilterchainconverter.h"
#include "mainwindow.h"
#include "localsinkgui.h"
#include "localsink.h"
#include "ui_localsinkgui.h"
LocalSinkGUI* LocalSinkGUI::create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *channelRx)
{
LocalSinkGUI* gui = new LocalSinkGUI(pluginAPI, deviceUISet, channelRx);
return gui;
}
void LocalSinkGUI::destroy()
{
delete this;
}
void LocalSinkGUI::setName(const QString& name)
{
setObjectName(name);
}
QString LocalSinkGUI::getName() const
{
return objectName();
}
qint64 LocalSinkGUI::getCenterFrequency() const {
return 0;
}
void LocalSinkGUI::setCenterFrequency(qint64 centerFrequency)
{
(void) centerFrequency;
}
void LocalSinkGUI::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
applySettings(true);
}
QByteArray LocalSinkGUI::serialize() const
{
return m_settings.serialize();
}
bool LocalSinkGUI::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
applySettings(true);
return true;
} else {
resetToDefaults();
return false;
}
}
bool LocalSinkGUI::handleMessage(const Message& message)
{
if (LocalSink::MsgSampleRateNotification::match(message))
{
LocalSink::MsgSampleRateNotification& notif = (LocalSink::MsgSampleRateNotification&) message;
//m_channelMarker.setBandwidth(notif.getSampleRate());
m_sampleRate = notif.getSampleRate();
displayRateAndShift();
return true;
}
else if (LocalSink::MsgConfigureLocalSink::match(message))
{
const LocalSink::MsgConfigureLocalSink& cfg = (LocalSink::MsgConfigureLocalSink&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
else
{
return false;
}
}
LocalSinkGUI::LocalSinkGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *channelrx, QWidget* parent) :
RollupWidget(parent),
ui(new Ui::LocalSinkGUI),
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_localSink = (LocalSink*) channelrx;
m_localSink->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(LocalSink::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);
}
LocalSinkGUI::~LocalSinkGUI()
{
m_deviceUISet->removeRxChannelInstance(this);
delete m_localSink; // TODO: check this: when the GUI closes it has to delete the demodulator
delete ui;
}
void LocalSinkGUI::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void LocalSinkGUI::applySettings(bool force)
{
if (m_doApplySettings)
{
setTitleColor(m_channelMarker.getColor());
LocalSink::MsgConfigureLocalSink* message = LocalSink::MsgConfigureLocalSink::create(m_settings, force);
m_localSink->getInputMessageQueue()->push(message);
}
}
void LocalSinkGUI::applyChannelSettings()
{
if (m_doApplySettings)
{
LocalSink::MsgConfigureChannelizer *msgChan = LocalSink::MsgConfigureChannelizer::create(
m_settings.m_log2Decim,
m_settings.m_filterChainHash);
m_localSink->getInputMessageQueue()->push(msgChan);
}
}
void LocalSinkGUI::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->decimationFactor->setCurrentIndex(m_settings.m_log2Decim);
applyDecimation();
blockApplySettings(false);
}
void LocalSinkGUI::displayRateAndShift()
{
int shift = m_shiftFrequencyFactor * m_sampleRate;
double channelSampleRate = ((double) m_sampleRate) / (1<<m_settings.m_log2Decim);
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 LocalSinkGUI::updateLocalDevices()
{
std::vector<uint32_t> localDevicesIndexes;
m_localSink->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 LocalSinkGUI::leaveEvent(QEvent*)
{
m_channelMarker.setHighlighted(false);
}
void LocalSinkGUI::enterEvent(QEvent*)
{
m_channelMarker.setHighlighted(true);
}
void LocalSinkGUI::handleSourceMessages()
{
Message* message;
while ((message = getInputMessageQueue()->pop()) != 0)
{
if (handleMessage(*message))
{
delete message;
}
}
}
void LocalSinkGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
(void) rollDown;
}
void LocalSinkGUI::onMenuDialogCalled(const QPoint &p)
{
BasicChannelSettingsDialog dialog(&m_channelMarker, this);
dialog.setUseReverseAPI(m_settings.m_useReverseAPI);
dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress);
dialog.setReverseAPIPort(m_settings.m_reverseAPIPort);
dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex);
dialog.setReverseAPIChannelIndex(m_settings.m_reverseAPIChannelIndex);
dialog.move(p);
dialog.exec();
m_settings.m_rgbColor = m_channelMarker.getColor().rgb();
m_settings.m_title = m_channelMarker.getTitle();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
m_settings.m_reverseAPIChannelIndex = dialog.getReverseAPIChannelIndex();
setWindowTitle(m_settings.m_title);
setTitleColor(m_settings.m_rgbColor);
applySettings();
}
void LocalSinkGUI::on_decimationFactor_currentIndexChanged(int index)
{
m_settings.m_log2Decim = index;
applyDecimation();
}
void LocalSinkGUI::on_position_valueChanged(int value)
{
m_settings.m_filterChainHash = value;
applyPosition();
}
void LocalSinkGUI::on_localDevice_currentIndexChanged(int index)
{
m_settings.m_localDeviceIndex = ui->localDevice->itemData(index).toInt();
applySettings();
}
void LocalSinkGUI::on_localDevicesRefresh_clicked(bool checked)
{
(void) checked;
updateLocalDevices();
}
void LocalSinkGUI::applyDecimation()
{
uint32_t maxHash = 1;
for (uint32_t i = 0; i < m_settings.m_log2Decim; i++) {
maxHash *= 3;
}
ui->position->setMaximum(maxHash-1);
ui->position->setValue(m_settings.m_filterChainHash);
m_settings.m_filterChainHash = ui->position->value();
applyPosition();
}
void LocalSinkGUI::applyPosition()
{
ui->filterChainIndex->setText(tr("%1").arg(m_settings.m_filterChainHash));
QString s;
m_shiftFrequencyFactor = HBFilterChainConverter::convertToString(m_settings.m_log2Decim, m_settings.m_filterChainHash, s);
ui->filterChainText->setText(s);
displayRateAndShift();
applyChannelSettings();
}
void LocalSinkGUI::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_CHANNELRX_LOCALSINK_LOCALSINKGUI_H_
#define PLUGINS_CHANNELRX_LOCALSINK_LOCALSINKGUI_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 "localsinksettings.h"
class PluginAPI;
class DeviceUISet;
class LocalSink;
class BasebandSampleSink;
namespace Ui {
class LocalSinkGUI;
}
class LocalSinkGUI : public RollupWidget, public PluginInstanceGUI {
Q_OBJECT
public:
static LocalSinkGUI* create(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
virtual void destroy();
void setName(const QString& name);
QString getName() const;
virtual qint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual bool handleMessage(const Message& message);
private:
Ui::LocalSinkGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
ChannelMarker m_channelMarker;
LocalSinkSettings m_settings;
int m_sampleRate;
quint64 m_deviceCenterFrequency; //!< Center frequency in device
double m_shiftFrequencyFactor; //!< Channel frequency shift factor
bool m_doApplySettings;
LocalSink* m_localSink;
MessageQueue m_inputMessageQueue;
QTime m_time;
uint32_t m_tickCount;
explicit LocalSinkGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel, QWidget* parent = 0);
virtual ~LocalSinkGUI();
void blockApplySettings(bool block);
void applySettings(bool force = false);
void applyChannelSettings();
void displaySettings();
void displayRateAndShift();
void updateLocalDevices();
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
void applyDecimation();
void applyPosition();
private slots:
void handleSourceMessages();
void on_decimationFactor_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,345 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LocalSinkGUI</class>
<widget class="RollupWidget" name="LocalSinkGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>100</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 sink</string>
</property>
<widget class="QWidget" name="settingsContainer" native="true">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>301</width>
<height>141</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="decimationLabel">
<property name="text">
<string>Dec</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="decimationFactor">
<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>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</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 "localsinkplugin.h"
#include <QtPlugin>
#include "plugin/pluginapi.h"
#ifndef SERVER_MODE
#include "localsinkgui.h"
#endif
#include "localsink.h"
const PluginDescriptor LocalSinkPlugin::m_pluginDescriptor = {
QString("Local channel sink"),
QString("4.6.0"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
QString("https://github.com/f4exb/sdrangel")
};
LocalSinkPlugin::LocalSinkPlugin(QObject* parent) :
QObject(parent),
m_pluginAPI(0)
{
}
const PluginDescriptor& LocalSinkPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void LocalSinkPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register channel Source
m_pluginAPI->registerRxChannel(LocalSink::m_channelIdURI, LocalSink::m_channelId, this);
}
#ifdef SERVER_MODE
PluginInstanceGUI* LocalSinkPlugin::createRxChannelGUI(
DeviceUISet *deviceUISet __attribute__((unused)),
BasebandSampleSink *rxChannel __attribute__((unused)))
{
return 0;
}
#else
PluginInstanceGUI* LocalSinkPlugin::createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel)
{
return LocalSinkGUI::create(m_pluginAPI, deviceUISet, rxChannel);
}
#endif
BasebandSampleSink* LocalSinkPlugin::createRxChannelBS(DeviceSourceAPI *deviceAPI)
{
return new LocalSink(deviceAPI);
}
ChannelSinkAPI* LocalSinkPlugin::createRxChannelCS(DeviceSourceAPI *deviceAPI)
{
return new LocalSink(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_CHANNELRX_LOCALSINK_LOCALSINKPLUGIN_H_
#define PLUGINS_CHANNELRX_LOCALSINK_LOCALSINKPLUGIN_H_
#include <QObject>
#include "plugin/plugininterface.h"
class DeviceUISet;
class BasebandSampleSink;
class LocalSinkPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "sdrangel.demod.localsink")
public:
explicit LocalSinkPlugin(QObject* parent = 0);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual PluginInstanceGUI* createRxChannelGUI(DeviceUISet *deviceUISet, BasebandSampleSink *rxChannel);
virtual BasebandSampleSink* createRxChannelBS(DeviceSourceAPI *deviceAPI);
virtual ChannelSinkAPI* createRxChannelCS(DeviceSourceAPI *deviceAPI);
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif /* PLUGINS_CHANNELRX_LOCALSINK_LOCALSINKPLUGIN_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 "localsinksettings.h"
#include <QColor>
#include "util/simpleserializer.h"
#include "settings/serializable.h"
LocalSinkSettings::LocalSinkSettings()
{
resetToDefaults();
}
void LocalSinkSettings::resetToDefaults()
{
m_localDeviceIndex = 0;
m_rgbColor = QColor(140, 4, 4).rgb();
m_title = "Local sink";
m_log2Decim = 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 LocalSinkSettings::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_log2Decim);
s.writeU32(13, m_filterChainHash);
return s.final();
}
bool LocalSinkSettings::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_log2Decim = 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_LOCALSINKSETTINGS_H_
#define INCLUDE_LOCALSINKSETTINGS_H_
#include <QByteArray>
#include <QString>
class Serializable;
struct LocalSinkSettings
{
uint32_t m_localDeviceIndex;
quint32 m_rgbColor;
QString m_title;
uint32_t m_log2Decim;
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;
LocalSinkSettings();
void resetToDefaults();
void setChannelMarker(Serializable *channelMarker) { m_channelMarker = channelMarker; }
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* INCLUDE_LOCALSINKSETTINGS_H_ */

Wyświetl plik

@ -0,0 +1,102 @@
///////////////////////////////////////////////////////////////////////////////////
// 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/samplesinkfifo.h"
#include "localsinkthread.h"
MESSAGE_CLASS_DEFINITION(LocalSinkThread::MsgStartStop, Message)
LocalSinkThread::LocalSinkThread(QObject* parent) :
QThread(parent),
m_running(false),
m_sampleFifo(0)
{
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
}
LocalSinkThread::~LocalSinkThread()
{
qDebug("LocalSinkThread::~LocalSinkThread");
}
void LocalSinkThread::startStop(bool start)
{
MsgStartStop *msg = MsgStartStop::create(start);
m_inputMessageQueue.push(msg);
}
void LocalSinkThread::startWork()
{
qDebug("LocalSinkThread::startWork");
m_startWaitMutex.lock();
start();
while(!m_running)
m_startWaiter.wait(&m_startWaitMutex, 100);
m_startWaitMutex.unlock();
}
void LocalSinkThread::stopWork()
{
qDebug("LocalSinkThread::stopWork");
m_running = false;
wait();
}
void LocalSinkThread::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 LocalSinkThread::processSamples(const quint8* data, uint count)
{
if (m_sampleFifo) {
m_sampleFifo->write(data, count);
}
}
void LocalSinkThread::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (MsgStartStop::match(*message))
{
MsgStartStop* notif = (MsgStartStop*) message;
qDebug("LocalSinkThread::handleInputMessages: MsgStartStop: %s", notif->getStartStop() ? "start" : "stop");
if (notif->getStartStop()) {
startWork();
} else {
stopWork();
}
delete message;
}
}
}

Wyświetl plik

@ -0,0 +1,80 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_CHANNELRX_LOCALSINK_LOCALSINKTHREAD_H_
#define PLUGINS_CHANNELRX_LOCALSINK_LOCALSINKTHREAD_H_
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include "dsp/dsptypes.h"
#include "util/message.h"
#include "util/messagequeue.h"
class SampleSinkFifo;
class LocalSinkThread : 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)
{ }
};
LocalSinkThread(QObject* parent = 0);
~LocalSinkThread();
void startStop(bool start);
void setSampleFifo(SampleSinkFifo *sampleFifo) { m_sampleFifo = sampleFifo; }
public slots:
void processSamples(const quint8* data, uint count);
private:
QMutex m_startWaitMutex;
QWaitCondition m_startWaiter;
volatile bool m_running;
SampleSinkFifo *m_sampleFifo;
MessageQueue m_inputMessageQueue;
void startWork();
void stopWork();
void run();
private slots:
void handleInputMessages();
};
#endif // PLUGINS_CHANNELRX_LOCALSINK_LOCALSINKTHREAD_H_

Wyświetl plik

@ -0,0 +1,74 @@
<h1>Remote sink channel plugin</h1>
<h2>Introduction</h2>
This plugin sends I/Q samples from the baseband via UDP to a distant network end point. It can use FEC protection to prevent possible data loss inherent to UDP protocol.
It is present only in Linux binary releases.
<h2>Build</h2>
The plugin will be built only if the [CM256cc library](https://github.com/f4exb/cm256cc) is installed in your system. For CM256cc library you will have to specify the include and library paths on the cmake command line. Say if you install cm256cc in `/opt/install/cm256cc` you will have to add `-DCM256CC_DIR=/opt/install/cm256cc` to the cmake commands.
<h2>Interface</h2>
![Remote sink channel plugin GUI](../../../doc/img/RemoteSink.png)
<h3>1: Decimation factor</h3>
The device baseband can be decimated in the channel and its center can be selected with (5). The resulting sample rate of the I/Q stream sent over the network is the baseband sample rate divided by this value. The value is displayed in (2).
<h3>2: Network I/Q stream sample rate</h3>
This is the sample rate in kS/s of the I/Q stream sent over the network.
<h3>3: Half-band filters chain sequence</h3>
This string represents the sequence of half-band filters used in the decimation from device baseband to resulting I/Q stream. Each character represents a filter type:
- **L**: lower half-band
- **H**: higher half-band
- **C**: centered
<h3>4: Center frequency shift</h3>
This is the shift of the channel center frequency from the device center frequency. Its value is driven by the device sample rate , the decimation (1) and the filter chain sequence (5).
<h3>5: Half-band filter chain sequence</h3>
The slider moves the channel center frequency roughly from the lower to the higher frequency in the device baseband. The number on the right represents the filter sequence as the decimal value of a base 3 number. Each base 3 digit represents the filter type and its sequence from MSB to LSB in the filter chain:
- **0**: lower half-band
- **1**: centered
- **2**: higher half-band
<h3>6: Distant address</h2>
IP address of the distant network interface from where the I/Q samples are sent via UDP
<h3>7: Data distant port</h2>
Distant port to which the I/Q samples are sent via UDP
<h3>8: Validation button</h3>
When the return key is hit within the address (1) or port (2) the changes are effective immediately. You can also use this button to set again these values.
<h3>9: Desired number of FEC blocks per frame</h3>
This sets the number of FEC blocks per frame. A frame consists of 128 data blocks (1 meta data block followed by 127 I/Q data blocks) and a variable number of FEC blocks used to protect the UDP transmission with a Cauchy MDS block erasure correction. The two numbers next are the total number of blocks and the number of FEC blocks separated by a slash (/).
<h3>10: Delay between UDP blocks transmission</h3>
This sets the minimum delay between transmission of an UDP block (send datagram) and the next. This allows throttling of the UDP transmission that is otherwise uncontrolled and causes network congestion.
The value is a percentage of the nominal time it takes to process a block of samples corresponding to one UDP block (512 bytes). This is calculated as follows:
- Sample rate on the network: _SR_
- Delay percentage: _d_
- Number of FEC blocks: _F_
- There are 127 blocks of I/Q data per frame (1 meta block for 128 blocks) and each I/Q data block of 512 bytes (128 samples) has a 8 bytes header (2 samples) thus there are 126 samples remaining effectively. This gives the constant 127*126 = 16002 samples per frame in the formula
Formula: ((127 &#x2715; 126 &#x2715; _d_) / _SR_) / (128 + _F_)
The percentage appears first at the right of the dial button and then the actual delay value in microseconds.

Wyświetl plik

@ -41,7 +41,7 @@
#include "dsp/hbfilterchainconverter.h"
#include "device/devicesourceapi.h"
#include "../remotesink/remotesinkthread.h"
#include "remotesinkthread.h"
MESSAGE_CLASS_DEFINITION(RemoteSink::MsgConfigureRemoteSink, Message)
MESSAGE_CLASS_DEFINITION(RemoteSink::MsgSampleRateNotification, Message)

Wyświetl plik

@ -102,5 +102,5 @@ if (BUILD_DEBIAN)
endif (BUILD_DEBIAN)
add_subdirectory(filesource)
add_subdirectory(localinput)
add_subdirectory(testsource)

Wyświetl plik

@ -110,6 +110,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
const std::vector<uint32_t>& getSampleRates() const { return m_sampleRates; }

Wyświetl plik

@ -111,6 +111,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
const std::vector<uint32_t>& getSampleRates() const { return m_sampleRates; }

Wyświetl plik

@ -113,6 +113,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -147,6 +147,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -120,6 +120,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -120,6 +120,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -289,6 +289,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
quint64 getStartingTimeStamp() const;

Wyświetl plik

@ -130,6 +130,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -218,6 +218,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -0,0 +1,72 @@
project(localinput)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(localinput_SOURCES
localinputgui.cpp
localinput.cpp
localinputsettings.cpp
localinputplugin.cpp
)
set(localinput_HEADERS
localinputgui.h
localinput.h
localinputsettings.h
localinputplugin.h
)
set(localinput_FORMS
localinputgui.ui
)
#include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
qt5_wrap_ui(localinput_FORMS_HEADERS ${localinput_FORMS})
add_library(inputlocal SHARED
${localinput_SOURCES}
${localinput_HEADERS_MOC}
${localinput_FORMS_HEADERS}
)
if (BUILD_DEBIAN)
target_include_directories(inputlocal PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${LIBCM256CCSRC}/..
)
else (BUILD_DEBIAN)
target_include_directories(inputlocal PUBLIC
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${CM256CC_INCLUDE_DIR}
)
endif (BUILD_DEBIAN)
if (BUILD_DEBIAN)
target_link_libraries(inputlocal
${QT_LIBRARIES}
cm256cc
sdrbase
sdrgui
swagger
)
else (BUILD_DEBIAN)
target_link_libraries(inputlocal
${QT_LIBRARIES}
${CM256CC_LIBRARIES}
sdrbase
sdrgui
swagger
)
endif (BUILD_DEBIAN)
target_link_libraries(inputlocal Qt5::Core Qt5::Widgets)
install(TARGETS inputlocal DESTINATION lib/plugins/samplesource)

Wyświetl plik

@ -0,0 +1,476 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 <string.h>
#include <errno.h>
#include <QDebug>
#include <QNetworkReply>
#include <QBuffer>
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
#include "SWGDeviceReport.h"
#include "SWGLocalInputReport.h"
#include "util/simpleserializer.h"
#include "dsp/dspcommands.h"
#include "dsp/dspengine.h"
#include "device/devicesourceapi.h"
#include "dsp/filerecord.h"
#include "localinput.h"
MESSAGE_CLASS_DEFINITION(LocalInput::MsgConfigureLocalInput, Message)
MESSAGE_CLASS_DEFINITION(LocalInput::MsgFileRecord, Message)
MESSAGE_CLASS_DEFINITION(LocalInput::MsgStartStop, Message)
MESSAGE_CLASS_DEFINITION(LocalInput::MsgReportSampleRateAndFrequency, Message)
LocalInput::LocalInput(DeviceSourceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_settings(),
m_deviceDescription("LocalInput"),
m_startingTimeStamp(0)
{
m_sampleFifo.setSize(96000 * 4);
m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
m_deviceAPI->addSink(m_fileSink);
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
}
LocalInput::~LocalInput()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
stop();
m_deviceAPI->removeSink(m_fileSink);
delete m_fileSink;
}
void LocalInput::destroy()
{
delete this;
}
void LocalInput::init()
{
applySettings(m_settings, true);
}
bool LocalInput::start()
{
qDebug() << "LocalInput::start";
return true;
}
void LocalInput::stop()
{
qDebug() << "LocalInput::stop";
}
QByteArray LocalInput::serialize() const
{
return m_settings.serialize();
}
bool LocalInput::deserialize(const QByteArray& data)
{
bool success = true;
if (!m_settings.deserialize(data))
{
m_settings.resetToDefaults();
success = false;
}
MsgConfigureLocalInput* message = MsgConfigureLocalInput::create(m_settings, true);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureLocalInput* messageToGUI = MsgConfigureLocalInput::create(m_settings, true);
m_guiMessageQueue->push(messageToGUI);
}
return success;
}
void LocalInput::setMessageQueueToGUI(MessageQueue *queue)
{
m_guiMessageQueue = queue;
}
const QString& LocalInput::getDeviceDescription() const
{
return m_deviceDescription;
}
int LocalInput::getSampleRate() const
{
return m_sampleRate;
}
void LocalInput::setSampleRate(int sampleRate)
{
m_sampleRate = sampleRate;
if (getMessageQueueToGUI())
{
MsgReportSampleRateAndFrequency *msg = MsgReportSampleRateAndFrequency::create(m_sampleRate, m_centerFrequency);
getMessageQueueToGUI()->push(msg);
}
}
quint64 LocalInput::getCenterFrequency() const
{
return m_centerFrequency;
}
void LocalInput::setCenterFrequency(qint64 centerFrequency)
{
m_centerFrequency = centerFrequency;
if (getMessageQueueToGUI())
{
MsgReportSampleRateAndFrequency *msg = MsgReportSampleRateAndFrequency::create(m_sampleRate, m_centerFrequency);
getMessageQueueToGUI()->push(msg);
}
}
std::time_t LocalInput::getStartingTimeStamp() const
{
return m_startingTimeStamp;
}
bool LocalInput::handleMessage(const Message& message)
{
if (DSPSignalNotification::match(message))
{
DSPSignalNotification& notif = (DSPSignalNotification&) message;
return m_fileSink->handleMessage(notif); // forward to file sink
}
else if (MsgFileRecord::match(message))
{
MsgFileRecord& conf = (MsgFileRecord&) message;
qDebug() << "LocalInput::handleMessage: MsgFileRecord: " << conf.getStartStop();
if (conf.getStartStop())
{
if (m_settings.m_fileRecordName.size() != 0) {
m_fileSink->setFileName(m_settings.m_fileRecordName);
} else {
m_fileSink->genUniqueFileName(m_deviceAPI->getDeviceUID());
}
m_fileSink->startRecording();
}
else
{
m_fileSink->stopRecording();
}
return true;
}
else if (MsgStartStop::match(message))
{
MsgStartStop& cmd = (MsgStartStop&) message;
qDebug() << "LocalInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
if (cmd.getStartStop())
{
if (m_deviceAPI->initAcquisition())
{
m_deviceAPI->startAcquisition();
}
}
else
{
m_deviceAPI->stopAcquisition();
}
if (m_settings.m_useReverseAPI) {
webapiReverseSendStartStop(cmd.getStartStop());
}
return true;
}
else if (MsgConfigureLocalInput::match(message))
{
qDebug() << "LocalInput::handleMessage:" << message.getIdentifier();
MsgConfigureLocalInput& conf = (MsgConfigureLocalInput&) message;
applySettings(conf.getSettings(), conf.getForce());
return true;
}
else
{
return false;
}
}
void LocalInput::applySettings(const LocalInputSettings& settings, bool force)
{
QMutexLocker mutexLocker(&m_mutex);
std::ostringstream os;
QString remoteAddress;
QList<QString> reverseAPIKeys;
if ((m_settings.m_dcBlock != settings.m_dcBlock) || force) {
reverseAPIKeys.append("dcBlock");
}
if ((m_settings.m_iqCorrection != settings.m_iqCorrection) || force) {
reverseAPIKeys.append("iqCorrection");
}
if ((m_settings.m_fileRecordName != settings.m_fileRecordName) || force) {
reverseAPIKeys.append("fileRecordName");
}
if ((m_settings.m_dcBlock != settings.m_dcBlock) || (m_settings.m_iqCorrection != settings.m_iqCorrection) || force)
{
m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection);
qDebug("LocalInput::applySettings: corrections: DC block: %s IQ imbalance: %s",
settings.m_dcBlock ? "true" : "false",
settings.m_iqCorrection ? "true" : "false");
}
mutexLocker.unlock();
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);
webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force);
}
m_settings = settings;
m_remoteAddress = remoteAddress;
qDebug() << "LocalInput::applySettings: "
<< " m_dcBlock: " << m_settings.m_dcBlock
<< " m_iqCorrection: " << m_settings.m_iqCorrection
<< " m_fileRecordName: " << m_settings.m_fileRecordName
<< " m_remoteAddress: " << m_remoteAddress;
}
int LocalInput::webapiRunGet(
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage)
{
(void) errorMessage;
m_deviceAPI->getDeviceEngineStateStr(*response.getState());
return 200;
}
int LocalInput::webapiRun(
bool run,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage)
{
(void) errorMessage;
m_deviceAPI->getDeviceEngineStateStr(*response.getState());
MsgStartStop *message = MsgStartStop::create(run);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgStartStop *msgToGUI = MsgStartStop::create(run);
m_guiMessageQueue->push(msgToGUI);
}
return 200;
}
int LocalInput::webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setLocalInputSettings(new SWGSDRangel::SWGLocalInputSettings());
response.getLocalInputSettings()->init();
webapiFormatDeviceSettings(response, m_settings);
return 200;
}
int LocalInput::webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage)
{
(void) errorMessage;
LocalInputSettings settings = m_settings;
if (deviceSettingsKeys.contains("dcBlock")) {
settings.m_dcBlock = response.getLocalInputSettings()->getDcBlock() != 0;
}
if (deviceSettingsKeys.contains("iqCorrection")) {
settings.m_iqCorrection = response.getLocalInputSettings()->getIqCorrection() != 0;
}
if (deviceSettingsKeys.contains("fileRecordName")) {
settings.m_fileRecordName = *response.getLocalInputSettings()->getFileRecordName();
}
if (deviceSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getLocalInputSettings()->getUseReverseApi() != 0;
}
if (deviceSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getLocalInputSettings()->getReverseApiAddress();
}
if (deviceSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getLocalInputSettings()->getReverseApiPort();
}
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getLocalInputSettings()->getReverseApiDeviceIndex();
}
MsgConfigureLocalInput *msg = MsgConfigureLocalInput::create(settings, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureLocalInput *msgToGUI = MsgConfigureLocalInput::create(settings, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatDeviceSettings(response, settings);
return 200;
}
void LocalInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const LocalInputSettings& settings)
{
response.getLocalInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
response.getLocalInputSettings()->setIqCorrection(settings.m_iqCorrection);
if (response.getLocalInputSettings()->getFileRecordName()) {
*response.getLocalInputSettings()->getFileRecordName() = settings.m_fileRecordName;
} else {
response.getLocalInputSettings()->setFileRecordName(new QString(settings.m_fileRecordName));
}
response.getLocalInputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getLocalInputSettings()->getReverseApiAddress()) {
*response.getLocalInputSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getLocalInputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getLocalInputSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getLocalInputSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
}
int LocalInput::webapiReportGet(
SWGSDRangel::SWGDeviceReport& response,
QString& errorMessage)
{
(void) errorMessage;
response.setLocalInputReport(new SWGSDRangel::SWGLocalInputReport());
response.getLocalInputReport()->init();
webapiFormatDeviceReport(response);
return 200;
}
void LocalInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
{
(void) response;
}
void LocalInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const LocalInputSettings& settings, bool force)
{
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
swgDeviceSettings->setTx(0);
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
swgDeviceSettings->setDeviceHwType(new QString("LocalInput"));
swgDeviceSettings->setLocalInputSettings(new SWGSDRangel::SWGLocalInputSettings());
SWGSDRangel::SWGLocalInputSettings *swgLocalInputSettings = swgDeviceSettings->getLocalInputSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (deviceSettingsKeys.contains("dcBlock") || force) {
swgLocalInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
}
if (deviceSettingsKeys.contains("iqCorrection") || force) {
swgLocalInputSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
}
if (deviceSettingsKeys.contains("fileRecordName") || force) {
swgLocalInputSettings->setFileRecordName(new QString(settings.m_fileRecordName));
}
QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/settings")
.arg(settings.m_reverseAPIAddress)
.arg(settings.m_reverseAPIPort)
.arg(settings.m_reverseAPIDeviceIndex);
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer=new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgDeviceSettings->asJson().toUtf8());
buffer->seek(0);
// Always use PATCH to avoid passing reverse API settings
m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
delete swgDeviceSettings;
}
void LocalInput::webapiReverseSendStartStop(bool start)
{
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
swgDeviceSettings->setTx(0);
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
swgDeviceSettings->setDeviceHwType(new QString("LocalInput"));
QString deviceSettingsURL = QString("http://%1:%2/sdrangel/deviceset/%3/device/run")
.arg(m_settings.m_reverseAPIAddress)
.arg(m_settings.m_reverseAPIPort)
.arg(m_settings.m_reverseAPIDeviceIndex);
m_networkRequest.setUrl(QUrl(deviceSettingsURL));
m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QBuffer *buffer=new QBuffer();
buffer->open((QBuffer::ReadWrite));
buffer->write(swgDeviceSettings->asJson().toUtf8());
buffer->seek(0);
if (start) {
m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
} else {
m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
}
}
void LocalInput::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "LocalInput::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
return;
}
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("LocalInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}

Wyświetl plik

@ -0,0 +1,192 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_REMOTEINPUT_H
#define INCLUDE_REMOTEINPUT_H
#include <ctime>
#include <iostream>
#include <stdint.h>
#include <QString>
#include <QByteArray>
#include <QTimer>
#include <QNetworkRequest>
#include "dsp/devicesamplesource.h"
#include "localinputsettings.h"
class QNetworkAccessManager;
class QNetworkReply;
class DeviceSourceAPI;
class FileRecord;
class LocalInput : public DeviceSampleSource {
Q_OBJECT
public:
class MsgConfigureLocalInput : public Message {
MESSAGE_CLASS_DECLARATION
public:
const LocalInputSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigureLocalInput* create(const LocalInputSettings& settings, bool force = false)
{
return new MsgConfigureLocalInput(settings, force);
}
private:
LocalInputSettings m_settings;
bool m_force;
MsgConfigureLocalInput(const LocalInputSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgFileRecord : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getStartStop() const { return m_startStop; }
static MsgFileRecord* create(bool startStop) {
return new MsgFileRecord(startStop);
}
protected:
bool m_startStop;
MsgFileRecord(bool startStop) :
Message(),
m_startStop(startStop)
{ }
};
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)
{ }
};
class MsgReportSampleRateAndFrequency : public Message {
MESSAGE_CLASS_DECLARATION
public:
int getSampleRate() const { return m_sampleRate; }
int getCenterFrequency() const { return m_centerFrequency; }
static MsgReportSampleRateAndFrequency* create(int sampleRate, qint64 centerFrequency) {
return new MsgReportSampleRateAndFrequency(sampleRate, centerFrequency);
}
protected:
int m_sampleRate;
qint64 m_centerFrequency;
MsgReportSampleRateAndFrequency(int sampleRate, qint64 centerFrequency) :
Message(),
m_sampleRate(sampleRate),
m_centerFrequency(centerFrequency)
{ }
};
LocalInput(DeviceSourceAPI *deviceAPI);
virtual ~LocalInput();
virtual void destroy();
virtual void init();
virtual bool start();
virtual void stop();
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual void setMessageQueueToGUI(MessageQueue *queue);
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate);
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
std::time_t getStartingTimeStamp() const;
virtual bool handleMessage(const Message& message);
virtual int webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage);
virtual int webapiReportGet(
SWGSDRangel::SWGDeviceReport& response,
QString& errorMessage);
virtual int webapiRunGet(
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage);
virtual int webapiRun(
bool run,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage);
private:
DeviceSourceAPI *m_deviceAPI;
QMutex m_mutex;
LocalInputSettings m_settings;
qint64 m_centerFrequency;
int m_sampleRate;
QString m_remoteAddress;
QString m_deviceDescription;
std::time_t m_startingTimeStamp;
FileRecord *m_fileSink; //!< File sink to record device I/Q output
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void applySettings(const LocalInputSettings& settings, bool force = false);
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const LocalInputSettings& settings);
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const LocalInputSettings& settings, bool force);
void webapiReverseSendStartStop(bool start);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif // INCLUDE_REMOTEINPUT_H

Wyświetl plik

@ -0,0 +1,58 @@
#--------------------------------------------------------
#
# Pro file for Android and Windows builds with Qt Creator
#
#--------------------------------------------------------
TEMPLATE = lib
CONFIG += plugin
QT += core gui widgets multimedia network opengl
TARGET = inputlocal
INCLUDEPATH += $$PWD
INCLUDEPATH += ../../../exports
INCLUDEPATH += ../../../sdrbase
INCLUDEPATH += ../../../sdrgui
INCLUDEPATH += ../../../swagger/sdrangel/code/qt5/client
macx:INCLUDEPATH += /opt/local/include
DEFINES += USE_SSE2=1
QMAKE_CXXFLAGS += -msse2
DEFINES += USE_SSSE3=1
QMAKE_CXXFLAGS += -mssse3
DEFINES += USE_SSE4_1=1
QMAKE_CXXFLAGS += -msse4.1
QMAKE_CXXFLAGS += -std=c++11
CONFIG(Release):build_subdir = release
CONFIG(Debug):build_subdir = debug
CONFIG(MINGW32):INCLUDEPATH += "C:\softs\boost_1_66_0"
CONFIG(MSVC):INCLUDEPATH += "C:\softs\boost_1_66_0"
CONFIG(macx):INCLUDEPATH += "../../../../../boost_1_69_0"
SOURCES += localinputgui.cpp\
localinput.cpp\
localinputsettings.cpp\
localinputplugin.cpp
HEADERS += localinputgui.h\
localinput.h\
localinputsettings.h\
localinputplugin.h
FORMS += localinputgui.ui
LIBS += -L../../../sdrbase/$${build_subdir} -lsdrbase
LIBS += -L../../../sdrgui/$${build_subdir} -lsdrgui
LIBS += -L../../../swagger/$${build_subdir} -lswagger
macx {
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/
}
RESOURCES = ../../../sdrgui/resources/res.qrc
CONFIG(MINGW32):DEFINES += USE_INTERNAL_TIMER=1

Wyświetl plik

@ -0,0 +1,371 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 <stdint.h>
#include <sstream>
#include <iostream>
#include <cassert>
#include <QDebug>
#include <QMessageBox>
#include <QTime>
#include <QDateTime>
#include <QString>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonParseError>
#include <QJsonObject>
#include "ui_localinputgui.h"
#include "gui/colormapper.h"
#include "gui/glspectrum.h"
#include "gui/crightclickenabler.h"
#include "gui/basicdevicesettingsdialog.h"
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "mainwindow.h"
#include "util/simpleserializer.h"
#include "device/devicesourceapi.h"
#include "device/deviceuiset.h"
#include "localinputgui.h"
LocalInputGui::LocalInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
QWidget(parent),
ui(new Ui::LocalInputGui),
m_deviceUISet(deviceUISet),
m_settings(),
m_sampleSource(0),
m_acquisition(false),
m_streamSampleRate(0),
m_streamCenterFrequency(0),
m_lastEngineState(DSPDeviceSourceEngine::StNotStarted),
m_framesDecodingStatus(0),
m_bufferLengthInSecs(0.0),
m_bufferGauge(-50),
m_nbOriginalBlocks(128),
m_nbFECBlocks(0),
m_sampleBits(16), // assume 16 bits to start with
m_sampleBytes(2),
m_samplesCount(0),
m_tickCount(0),
m_addressEdited(false),
m_dataPortEdited(false),
m_countUnrecoverable(0),
m_countRecovered(0),
m_doApplySettings(true),
m_forceSettings(true),
m_txDelay(0.0)
{
m_paletteGreenText.setColor(QPalette::WindowText, Qt::green);
m_paletteWhiteText.setColor(QPalette::WindowText, Qt::white);
m_startingTimeStampms = 0;
ui->setupUi(this);
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->centerFrequency->setValueRange(7, 0, 9999999U);
ui->centerFrequencyHz->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->centerFrequencyHz->setValueRange(3, 0, 999U);
CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop);
connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &)));
displaySettings();
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
m_statusTimer.start(500);
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
m_sampleSource = (LocalInput*) m_deviceUISet->m_deviceSourceAPI->getSampleSource();
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
m_sampleSource->setMessageQueueToGUI(&m_inputMessageQueue);
m_networkManager = new QNetworkAccessManager();
connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
m_eventsTime.start();
m_forceSettings = true;
sendSettings();
}
LocalInputGui::~LocalInputGui()
{
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
delete ui;
}
void LocalInputGui::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void LocalInputGui::destroy()
{
delete this;
}
void LocalInputGui::setName(const QString& name)
{
setObjectName(name);
}
QString LocalInputGui::getName() const
{
return objectName();
}
void LocalInputGui::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
m_forceSettings = true;
sendSettings();
}
QByteArray LocalInputGui::serialize() const
{
return m_settings.serialize();
}
bool LocalInputGui::deserialize(const QByteArray& data)
{
qDebug("LocalInputGui::deserialize");
if (m_settings.deserialize(data))
{
displaySettings();
m_forceSettings = true;
sendSettings();
return true;
}
else
{
return false;
}
}
qint64 LocalInputGui::getCenterFrequency() const
{
return m_streamCenterFrequency;
}
void LocalInputGui::setCenterFrequency(qint64 centerFrequency)
{
(void) centerFrequency;
}
bool LocalInputGui::handleMessage(const Message& message)
{
if (LocalInput::MsgConfigureLocalInput::match(message))
{
const LocalInput::MsgConfigureLocalInput& cfg = (LocalInput::MsgConfigureLocalInput&) message;
m_settings = cfg.getSettings();
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
else if (LocalInput::MsgStartStop::match(message))
{
LocalInput::MsgStartStop& notif = (LocalInput::MsgStartStop&) message;
blockApplySettings(true);
ui->startStop->setChecked(notif.getStartStop());
blockApplySettings(false);
return true;
}
else if (LocalInput::MsgReportSampleRateAndFrequency::match(message))
{
LocalInput::MsgReportSampleRateAndFrequency& notif = (LocalInput::MsgReportSampleRateAndFrequency&) message;
m_streamSampleRate = notif.getSampleRate();
m_streamCenterFrequency = notif.getCenterFrequency();
updateSampleRateAndFrequency();
return true;
}
else
{
return false;
}
}
void LocalInputGui::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
//qDebug("LocalInputGui::handleInputMessages: message: %s", message->getIdentifier());
if (DSPSignalNotification::match(*message))
{
DSPSignalNotification* notif = (DSPSignalNotification*) message;
if (notif->getSampleRate() != m_streamSampleRate) {
m_streamSampleRate = notif->getSampleRate();
}
m_streamCenterFrequency = notif->getCenterFrequency();
qDebug("LocalInputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
updateSampleRateAndFrequency();
DSPSignalNotification *fwd = new DSPSignalNotification(*notif);
m_sampleSource->getInputMessageQueue()->push(fwd);
delete message;
}
else
{
if (handleMessage(*message))
{
delete message;
}
}
}
}
void LocalInputGui::updateSampleRateAndFrequency()
{
m_deviceUISet->getSpectrum()->setSampleRate(m_streamSampleRate);
m_deviceUISet->getSpectrum()->setCenterFrequency(m_streamCenterFrequency);
ui->deviceRateText->setText(tr("%1k").arg((float)m_streamSampleRate / 1000));
blockApplySettings(true);
ui->centerFrequency->setValue(m_streamCenterFrequency / 1000);
ui->centerFrequencyHz->setValue(m_streamCenterFrequency % 1000);
blockApplySettings(false);
}
void LocalInputGui::displaySettings()
{
blockApplySettings(true);
ui->centerFrequency->setValue(m_streamCenterFrequency / 1000);
ui->centerFrequencyHz->setValue(m_streamCenterFrequency % 1000);
ui->deviceRateText->setText(tr("%1k").arg(m_streamSampleRate / 1000.0));
ui->dcOffset->setChecked(m_settings.m_dcBlock);
ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
blockApplySettings(false);
}
void LocalInputGui::sendSettings()
{
if(!m_updateTimer.isActive())
m_updateTimer.start(100);
}
void LocalInputGui::on_dcOffset_toggled(bool checked)
{
m_settings.m_dcBlock = checked;
sendSettings();
}
void LocalInputGui::on_iqImbalance_toggled(bool checked)
{
m_settings.m_iqCorrection = checked;
sendSettings();
}
void LocalInputGui::on_startStop_toggled(bool checked)
{
if (m_doApplySettings)
{
LocalInput::MsgStartStop *message = LocalInput::MsgStartStop::create(checked);
m_sampleSource->getInputMessageQueue()->push(message);
}
}
void LocalInputGui::on_record_toggled(bool checked)
{
if (checked) {
ui->record->setStyleSheet("QToolButton { background-color : red; }");
} else {
ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
}
LocalInput::MsgFileRecord* message = LocalInput::MsgFileRecord::create(checked);
m_sampleSource->getInputMessageQueue()->push(message);
}
void LocalInputGui::updateHardware()
{
if (m_doApplySettings)
{
qDebug() << "LocalInputGui::updateHardware";
LocalInput::MsgConfigureLocalInput* message =
LocalInput::MsgConfigureLocalInput::create(m_settings, m_forceSettings);
m_sampleSource->getInputMessageQueue()->push(message);
m_forceSettings = false;
m_updateTimer.stop();
}
}
void LocalInputGui::updateStatus()
{
int state = m_deviceUISet->m_deviceSourceAPI->state();
if(m_lastEngineState != state)
{
switch(state)
{
case DSPDeviceSourceEngine::StNotStarted:
ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
break;
case DSPDeviceSourceEngine::StIdle:
ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
break;
case DSPDeviceSourceEngine::StRunning:
ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
break;
case DSPDeviceSourceEngine::StError:
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceSourceAPI->errorMessage());
break;
default:
break;
}
m_lastEngineState = state;
}
}
void LocalInputGui::openDeviceSettingsDialog(const QPoint& p)
{
BasicDeviceSettingsDialog dialog(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.move(p);
dialog.exec();
m_settings.m_useReverseAPI = dialog.useReverseAPI();
m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress();
m_settings.m_reverseAPIPort = dialog.getReverseAPIPort();
m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex();
sendSettings();
}

Wyświetl plik

@ -0,0 +1,127 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_REMOTEINPUTGUI_H
#define INCLUDE_REMOTEINPUTGUI_H
#include <QTimer>
#include <QWidget>
#include <QNetworkRequest>
#include "plugin/plugininstancegui.h"
#include "util/messagequeue.h"
#include "localinput.h"
class DeviceUISet;
class QNetworkAccessManager;
class QNetworkReply;
class QJsonObject;
namespace Ui {
class LocalInputGui;
}
class LocalInputGui : public QWidget, public PluginInstanceGUI {
Q_OBJECT
public:
explicit LocalInputGui(DeviceUISet *deviceUISet, QWidget* parent = 0);
virtual ~LocalInputGui();
virtual void destroy();
void setName(const QString& name);
QString getName() const;
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual qint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
virtual bool handleMessage(const Message& message);
private:
Ui::LocalInputGui* ui;
DeviceUISet* m_deviceUISet;
LocalInputSettings m_settings; //!< current settings
LocalInput* m_sampleSource;
bool m_acquisition;
int m_streamSampleRate; //!< Sample rate of received stream
quint64 m_streamCenterFrequency; //!< Center frequency of received stream
QTimer m_updateTimer;
QTimer m_statusTimer;
int m_lastEngineState;
MessageQueue m_inputMessageQueue;
// int m_sampleRate;
// quint64 m_centerFrequency;
uint64_t m_startingTimeStampms;
int m_framesDecodingStatus;
bool m_allBlocksReceived;
float m_bufferLengthInSecs;
int32_t m_bufferGauge;
int m_minNbBlocks;
int m_minNbOriginalBlocks;
int m_maxNbRecovery;
float m_avgNbBlocks;
float m_avgNbOriginalBlocks;
float m_avgNbRecovery;
int m_nbOriginalBlocks;
int m_nbFECBlocks;
int m_sampleBits;
int m_sampleBytes;
int m_samplesCount;
std::size_t m_tickCount;
bool m_addressEdited;
bool m_dataPortEdited;
uint32_t m_countUnrecoverable;
uint32_t m_countRecovered;
QTime m_eventsTime;
bool m_doApplySettings;
bool m_forceSettings;
double m_txDelay;
QPalette m_paletteGreenText;
QPalette m_paletteWhiteText;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
void blockApplySettings(bool block);
void displaySettings();
void displayTime();
void sendSettings();
void updateSampleRateAndFrequency();
private slots:
void handleInputMessages();
void on_dcOffset_toggled(bool checked);
void on_iqImbalance_toggled(bool checked);
void on_startStop_toggled(bool checked);
void on_record_toggled(bool checked);
void updateHardware();
void updateStatus();
void openDeviceSettingsDialog(const QPoint& p);
};
#endif // INCLUDE_REMOTEINPUTGUI_H

Wyświetl plik

@ -0,0 +1,296 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LocalInputGui</class>
<widget class="QWidget" name="LocalInputGui">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>100</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>100</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Local Input</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="horizontalLayout_freq">
<property name="topMargin">
<number>4</number>
</property>
<item>
<layout class="QVBoxLayout" name="deviceUILayout">
<item>
<layout class="QHBoxLayout" name="deviceButtonsLayout">
<item>
<widget class="ButtonSwitch" name="startStop">
<property name="toolTip">
<string>start/stop acquisition</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/play.png</normaloff>
<normalon>:/stop.png</normalon>:/play.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="record">
<property name="toolTip">
<string>Toggle record I/Q samples from device</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/record_off.png</normaloff>:/record_off.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="deviceRateLayout">
<item>
<widget class="QLabel" name="deviceRateText">
<property name="toolTip">
<string>I/Q sample rate kS/s</string>
</property>
<property name="text">
<string>00000k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="freqLeftSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="ValueDial" name="centerFrequency" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<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>20</pointsize>
</font>
</property>
<property name="cursor">
<cursorShape>ForbiddenCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Remote center frequency kHz</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="hertzLayout">
<item>
<widget class="ValueDial" name="centerFrequencyHz" native="true">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<family>Liberation Mono</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="cursor">
<cursorShape>ForbiddenCursor</cursorShape>
</property>
<property name="toolTip">
<string>Remote center frequency sub kHz</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="freqUnits">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string> Hz</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</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>
</layout>
</item>
<item>
<widget class="Line" name="line_address">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="gridLayout_corr">
<item>
<widget class="ButtonSwitch" name="dcOffset">
<property name="toolTip">
<string>DC Offset auto correction</string>
</property>
<property name="text">
<string>DC</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="iqImbalance">
<property name="toolTip">
<string>IQ Imbalance auto correction</string>
</property>
<property name="text">
<string>IQ</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>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="padLayout">
<item>
<spacer name="verticalPadSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ValueDial</class>
<extends>QWidget</extends>
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

Wyświetl plik

@ -0,0 +1,114 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 <QtPlugin>
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "device/devicesourceapi.h"
#ifdef SERVER_MODE
#include "localinput.h"
#else
#include "localinputgui.h"
#endif
#include "localinputplugin.h"
const PluginDescriptor LocalInputPlugin::m_pluginDescriptor = {
QString("Local device input"),
QString("4.6.0"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
QString("https://github.com/f4exb/sdrangel")
};
const QString LocalInputPlugin::m_hardwareID = "LocalInput";
const QString LocalInputPlugin::m_deviceTypeID = LOCALINPUT_DEVICE_TYPE_ID;
LocalInputPlugin::LocalInputPlugin(QObject* parent) :
QObject(parent)
{
}
const PluginDescriptor& LocalInputPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void LocalInputPlugin::initPlugin(PluginAPI* pluginAPI)
{
pluginAPI->registerSampleSource(m_deviceTypeID, this);
}
PluginInterface::SamplingDevices LocalInputPlugin::enumSampleSources()
{
SamplingDevices result;
result.append(SamplingDevice(
"LocalInput",
m_hardwareID,
m_deviceTypeID,
QString::null,
0,
PluginInterface::SamplingDevice::BuiltInDevice,
true,
1,
0));
return result;
}
#ifdef SERVER_MODE
PluginInstanceGUI* LocalInputPlugin::createSampleSourcePluginInstanceGUI(
const QString& sourceId __attribute((unused)),
QWidget **widget __attribute((unused)),
DeviceUISet *deviceUISet __attribute((unused)))
{
return 0;
}
#else
PluginInstanceGUI* LocalInputPlugin::createSampleSourcePluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet)
{
if(sourceId == m_deviceTypeID)
{
LocalInputGui* gui = new LocalInputGui(deviceUISet);
*widget = gui;
return gui;
}
else
{
return 0;
}
}
#endif
DeviceSampleSource *LocalInputPlugin::createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI)
{
if (sourceId == m_deviceTypeID)
{
LocalInput* input = new LocalInput(deviceAPI);
return input;
}
else
{
return 0;
}
}

Wyświetl plik

@ -0,0 +1,53 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_LOCALINPUTPLUGIN_H
#define INCLUDE_LOCALINPUTPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
#define LOCALINPUT_DEVICE_TYPE_ID "sdrangel.samplesource.localinput"
class PluginAPI;
class LocalInputPlugin : public QObject, public PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID LOCALINPUT_DEVICE_TYPE_ID)
public:
explicit LocalInputPlugin(QObject* parent = NULL);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual SamplingDevices enumSampleSources();
virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet);
virtual DeviceSampleSource* createSampleSourcePluginInstanceInput(const QString& sourceId, DeviceSourceAPI *deviceAPI);
static const QString m_hardwareID;
static const QString m_deviceTypeID;
private:
static const PluginDescriptor m_pluginDescriptor;
};
#endif // INCLUDE_LOCALINPUTPLUGIN_H

Wyświetl plik

@ -0,0 +1,89 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 "util/simpleserializer.h"
#include "localinputsettings.h"
LocalInputSettings::LocalInputSettings()
{
resetToDefaults();
}
void LocalInputSettings::resetToDefaults()
{
m_dcBlock = false;
m_iqCorrection = false;
m_fileRecordName = "";
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
}
QByteArray LocalInputSettings::serialize() const
{
SimpleSerializer s(1);
s.writeBool(1, m_dcBlock);
s.writeBool(2, m_iqCorrection);
s.writeBool(3, m_useReverseAPI);
s.writeString(4, m_reverseAPIAddress);
s.writeU32(5, m_reverseAPIPort);
s.writeU32(6, m_reverseAPIDeviceIndex);
return s.final();
}
bool LocalInputSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
quint32 uintval;
d.readBool(1, &m_dcBlock, false);
d.readBool(2, &m_iqCorrection, false);
d.readBool(3, &m_useReverseAPI, false);
d.readString(4, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(5, &uintval, 0);
if ((uintval > 1023) && (uintval < 65535)) {
m_reverseAPIPort = uintval;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(6, &uintval, 0);
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
return true;
}
else
{
resetToDefaults();
return false;
}
}

Wyświetl plik

@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_SAMPLESOURCE_LOCALINPUT_LOCALINPUTSETTINGS_H_
#define PLUGINS_SAMPLESOURCE_LOCALINPUT_LOCALINPUTSETTINGS_H_
#include <QByteArray>
#include <QString>
struct LocalInputSettings {
bool m_dcBlock;
bool m_iqCorrection;
QString m_fileRecordName;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
LocalInputSettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* PLUGINS_SAMPLESOURCE_LOCALINPUT_LOCALINPUTSETTINGS_H_ */

Wyświetl plik

@ -0,0 +1,173 @@
<h1>Remote input plugin</h1>
<h2>Introduction</h2>
This input sample source plugin gets its samples over tbe network from a SDRangel instance's Remote channel sink using UDP connection.
Forward Error Correction with a Cauchy MDS block erasure codec is used to prevent block loss. This can make the UDP transmission more robust particularly over WiFi links.
Please note that there is no provision for handling out of sync UDP blocks. It is assumed that frames and block numbers always increase with possible blocks missing. Such out of sync situation has never been encountered in practice.
The distant SDRangel instance that sends the data stream is controlled via its REST API using a separate control software for example [SDRangelcli](https://github.com/f4exb/sdrangelcli)
A sample size conversion takes place if the stream sample size sent by the distant instance and the Rx sample size of the local instance do not match (i.e. 16 to 24 bits or 24 to 16 bits). Best performace is obtained when both instances use the same sample size.
It is present only in Linux binary releases.
<h2>Build</h2>
The plugin will be built only if the [CM256cc library](https://github.com/f4exb/cm256cc) is installed in your system. For CM256cc library you will have to specify the include and library paths on the cmake command line. Say if you install cm256cc in `/opt/install/cm256cc` you will have to add `-DCM256CC_DIR=/opt/install/cm256cc` to the cmake commands.
<h2>Interface</h2>
![SDR Remote input plugin GUI](../../../doc/img/RemoteInput_plugin.png)
<h3>1: Start/Stop</h3>
Device start / stop button.
- Blue triangle icon: device is ready and can be started
- Green square icon: device is running and can be stopped
<h3>2: Record</h3>
Record I/Q stream toggle button
<h3>3: Frequency</h3>
This is the center frequency in Hz sent in the meta data from the distant SDRangel instance and corresponds to the center frequency of reception. The sub kHz value (000 to 999 Hz) is represented in smaller digits on the right.
<h3>4: Stream sample rate</h3>
Stream I/Q sample rate in kS/s
<h3>5: Auto correction options and stream status</h3>
![SDR Remote input stream GUI](../../../doc/img/RemoteInput_plugin_02.png)
<h4>5.1: Auto correction options</h4>
These buttons control the local DSP auto correction options:
- **DC**: auto remove DC component
- **IQ**: auto make I/Q balance
<h4>5.2: Receive buffer length</h4>
This is the main buffer (writes from UDP / reads from DSP engine) length in units of time (seconds). As read and write pointers are normally about half the buffer apart the nominal delay introduced by the buffer is the half of this value.
<h4>5.3: Main buffer R/W pointers positions</h4>
Read and write pointers should always be a half buffer distance buffer apart. This is the difference in percent of the main buffer size from this ideal position.
- When positive it means that the read pointer is leading
- When negative it means that the write pointer is leading (read is lagging)
This corresponds to the value shown in the gauges above (9)
<h4>5.4: Date/time</h4>
This is the current timestamp of the block of data sent from the receiver. It is refreshed about every second. The plugin tries to take into account the buffer that is used between the data received from the network and the data effectively used by the system however this may not be extremely accurate. It is based on the timestamps sent from the Remote sink channel at the other hand that does not take into account its own buffers.
<h3>6: Main buffer R/W pointers gauge</h3>
There are two gauges separated by a dot in the center. Ideally these gauges should not display any value thus read and write pointers are always half a buffer apart. However due to the fact that a whole frame is reconstructed at once up to ~10% variation is normal and should appear on the left gauge (write leads).
- The left gauge is the negative gauge. It is the value in percent of buffer size from the write pointer position to the read pointer position when this difference is less than half of a buffer distance. It means that the writes are leading or reads are lagging.
- The right gauge is the positive gauge. It is the value in percent of buffer size of the difference from the read pointer position to the write pointer position when this difference is less than half of a buffer distance. It menas that the writes are lagging or reads are leading.
The system tries to compensate read / write unbalance however at start or when a large stream disruption has occurred a delay of a few tens of seconds is necessary before read / write reaches equilibrium.
<h3>7: Data stream status</h3>
![SDR Remote input stream GUI](../../../doc/img/RemoteInput_plugin_04.png)
<h4>7.1: Sample size</h4>
This is the size in bits of a I or Q sample sent in the stream by the distant server.
<h4>7.2: Total number of frames and number of FEC blocks</h4>
This is the total number of frames and number of FEC blocks separated by a slash '/' as sent in the meta data block thus acknowledged by the distant server. When you set the number of FEC blocks with (4.1) the effect may not be immediate and this information can be used to monitor when it gets effectively set in the distant server.
A frame consists of 128 data blocks (1 meta data block followed by 127 I/Q data blocks) and a variable number of FEC blocks used to protect the UDP transmission with a Cauchy MDS block erasure correction.
Using the Cauchy MDS block erasure correction ensures that if at least the number of data blocks (128) is received per complete frame then all lost blocks in any position can be restored. For example if 8 FEC blocks are used then 136 blocks are transmitted per frame. If only 130 blocks (128 or greater) are received then data can be recovered. If only 127 blocks (or less) are received then none of the lost blocks can be recovered.
<h4>7.3: Stream status</h4>
The color of the icon indicates stream status:
- Green: all original blocks have been received for all frames during the last polling timeframe (ex: 136)
- No color: some original blocks were reconstructed from FEC blocks for some frames during the last polling timeframe (ex: between 128 and 135)
- Red: some original blocks were definitely lost for some frames during the last polling timeframe (ex: less than 128)
<h4>7.4: Minimum total number of blocks per frame</h4>
This is the minimum total number of blocks per frame during the last polling period. If all blocks were received for all frames then this number is the nominal number of original blocks plus FEC blocks (Green lock icon). In our example this is 128+8 = 136.
If this number falls below 128 then some blocks are definitely lost and the lock lights in red.
<h4>7.5: Maximum number of FEC blocks used by frame</h4>
Maximum number of FEC blocks used for original blocks recovery during the last polling timeframe. Ideally this should be 0 when no blocks are lost but the system is able to correct lost blocks up to the nominal number of FEC blocks (Neutral lock icon).
<h4>7.6: Reset events counters</h4>
This push button can be used to reset the events counters (4.7 and 4.8) and reset the event counts timer (4.9)
<h4>7.7: Unrecoverable error events counter</h4>
This counter counts the unrecoverable error conditions found (i.e. 4.4 lower than 128) since the last counters reset.
<h4>7.8: Recoverable error events counter</h4>
This counter counts the unrecoverable error conditions found (i.e. 4.4 between 128 and 128 plus the number of FEC blocks) since the last counters reset.
<h4>7.9: events counters timer</h4>
This HH:mm:ss time display shows the time since the reset events counters button (4.6) was pushed.
<h3>8: Distant server API address and port</h3>
![SDR Remote input stream GUI](../../../doc/img/RemoteInput_plugin_05.png)
<h4>8.1: API connection indicator</h4>
The "API" label is lit in green when the connection is successful
<h4>8.2: API IP address</h4>
IP address of the distant SDRangel instance REST API
<h4>8.3: API port</h4>
Port of the distant SDRangel instance REST API
<h4>8.4: Validation button</h4>
When the return key is hit within the address (5.2) or port (5.3) the changes are effective immediately. You can also use this button to set again these values. Clicking on this button will send a request to the API to get the distant SDRangel instance information that is displayed in the API message box (8)
<h3>9: Local data address and port</h3>
![SDR Remote source input stream GUI](../../../doc/img/RemoteInput_plugin_06.png)
<h4>9.1: Data IP address</h4>
IP address of the local network interface the distant SDRangel instance sends the data to
<h4>9.2: Data port</h4>
Local port the distant SDRangel instance sends the data to
<h4>9.3: Validation button</h4>
When the return key is hit within the address (5.2) or port (5.3) the changes are effective immediately. You can also use this button to set again these values.
<h3>10: Status message</h3>
The API status is displayed in this box. It shows "API OK" when the connection is successful and reply is OK
<h3>11: API information</h3>
This is the information returned by the API and is the distance SDRangel instance information if transaction is successful

Wyświetl plik

@ -111,6 +111,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -113,6 +113,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -20,7 +20,7 @@ set(remoteinput_SOURCES
remoteinputplugin.cpp
)
set(sremoteinput_HEADERS
set(remoteinput_HEADERS
remoteinputbuffer.h
remoteinputudphandler.h
remoteinputgui.h

Wyświetl plik

@ -282,6 +282,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue);
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
std::time_t getStartingTimeStamp() const;

Wyświetl plik

@ -111,6 +111,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -149,6 +149,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -154,6 +154,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -110,6 +110,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);

Wyświetl plik

@ -206,6 +206,7 @@ public:
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual void setSampleRate(int sampleRate) { (void) sampleRate; }
uint32_t getDevSampleRate() const;
uint32_t getLog2HardDecim() const;
double getClockGen() const;

Wyświetl plik

@ -37,6 +37,7 @@ SUBDIRS += plugins/samplesource/filesource
SUBDIRS += plugins/samplesource/hackrfinput
SUBDIRS += plugins/samplesource/limesdrinput
SUBDIRS += plugins/samplesource/plutosdrinput
SUBDIRS += plugins/samplesource/localinput
CONFIG(MSVC):SUBDIRS += plugins/samplesource/remoteinput
SUBDIRS += plugins/samplesource/rtlsdr
CONFIG(MSVC):SUBDIRS += plugins/samplesource/soapysdrinput
@ -60,6 +61,7 @@ SUBDIRS += plugins/channelrx/demodnfm
SUBDIRS += plugins/channelrx/demodssb
SUBDIRS += plugins/channelrx/demodwfm
SUBDIRS += plugins/channelrx/udpsink
SUBDIRS += plugins/channelrx/localsink
SUBDIRS += plugins/channeltx/modam
SUBDIRS += plugins/channeltx/modnfm
SUBDIRS += plugins/channeltx/modssb

Wyświetl plik

@ -23,6 +23,7 @@
ChannelSinkAPI::ChannelSinkAPI(const QString& name) :
m_name(name),
m_indexInDeviceSet(-1),
m_deviceSourceAPI(0),
m_uid(UidCalculator::getNewObjectId())
{
}

Wyświetl plik

@ -26,6 +26,8 @@
#include "export.h"
class DeviceSourceAPI;
namespace SWGSDRangel
{
class SWGChannelSettings;
@ -79,6 +81,8 @@ public:
void setIndexInDeviceSet(int indexInDeviceSet) { m_indexInDeviceSet = indexInDeviceSet; }
int getDeviceSetIndex() const { return m_deviceSetIndex; }
void setDeviceSetIndex(int deviceSetIndex) { m_deviceSetIndex = deviceSetIndex; }
DeviceSourceAPI *getDeviceSourceAPI() { return m_deviceSourceAPI; }
void setDeviceSourceAPI(DeviceSourceAPI *deviceSourceAPI) { m_deviceSourceAPI = deviceSourceAPI; }
uint64_t getUID() const { return m_uid; }
private:
@ -89,6 +93,7 @@ private:
int m_indexInDeviceSet;
int m_deviceSetIndex;
DeviceSourceAPI *m_deviceSourceAPI;
uint64_t m_uid;
};

Wyświetl plik

@ -23,6 +23,7 @@
ChannelSourceAPI::ChannelSourceAPI(const QString& name) :
m_name(name),
m_indexInDeviceSet(-1),
m_deviceSinkAPI(0),
m_uid(UidCalculator::getNewObjectId())
{ }

Wyświetl plik

@ -25,6 +25,8 @@
#include "export.h"
class DeviceSinkAPI;
namespace SWGSDRangel
{
class SWGChannelSettings;
@ -78,6 +80,8 @@ public:
void setIndexInDeviceSet(int indexInDeviceSet) { m_indexInDeviceSet = indexInDeviceSet; }
int getDeviceSetIndex() const { return m_deviceSetIndex; }
void setDeviceSetIndex(int deviceSetIndex) { m_deviceSetIndex = deviceSetIndex; }
DeviceSinkAPI *getDeviceSinkAPI() { return m_deviceSinkAPI; }
void setDeviceSinkAPI(DeviceSinkAPI *deviceSinkAPI) { m_deviceSinkAPI = deviceSinkAPI; }
uint64_t getUID() const { return m_uid; }
private:
@ -88,6 +92,7 @@ private:
int m_indexInDeviceSet;
int m_deviceSetIndex;
DeviceSinkAPI *m_deviceSinkAPI;
uint64_t m_uid;
};

Wyświetl plik

@ -103,6 +103,7 @@ void DeviceSinkAPI::renumerateChannels()
{
m_channelAPIs.at(i)->setIndexInDeviceSet(i);
m_channelAPIs.at(i)->setDeviceSetIndex(m_deviceTabIndex);
m_channelAPIs.at(i)->setDeviceSinkAPI(this);
}
}

Wyświetl plik

@ -93,6 +93,7 @@ void DeviceSourceAPI::renumerateChannels()
{
m_channelAPIs.at(i)->setIndexInDeviceSet(i);
m_channelAPIs.at(i)->setDeviceSetIndex(m_deviceTabIndex);
m_channelAPIs.at(i)->setDeviceSourceAPI(this);
}
}

Wyświetl plik

@ -61,6 +61,7 @@ public:
virtual const QString& getDeviceDescription() const = 0;
virtual int getSampleRate() const = 0; //!< Sample rate exposed by the source
virtual void setSampleRate(int sampleRate) = 0; //!< For when the source sample rate is set externally
virtual quint64 getCenterFrequency() const = 0; //!< Center frequency exposed by the source
virtual void setCenterFrequency(qint64 centerFrequency) = 0;

Wyświetl plik

@ -52,9 +52,11 @@ public:
AudioDeviceManager *getAudioDeviceManager() { return &m_audioDeviceManager; }
uint32_t getDeviceSourceEnginesNumber() const { return m_deviceSourceEngines.size(); }
DSPDeviceSourceEngine *getDeviceSourceEngineByIndex(uint deviceIndex) { return m_deviceSourceEngines[deviceIndex]; }
DSPDeviceSourceEngine *getDeviceSourceEngineByUID(uint uid);
uint32_t getDeviceSinkEnginesNumber() const { return m_deviceSinkEngines.size(); }
DSPDeviceSinkEngine *getDeviceSinkEngineByIndex(uint deviceIndex) { return m_deviceSinkEngines[deviceIndex]; }
DSPDeviceSinkEngine *getDeviceSinkEngineByUID(uint uid);

Wyświetl plik

@ -33,6 +33,8 @@
#include "plugin/pluginmanager.h"
const QString PluginManager::m_localInputHardwareID = "LocalInput";
const QString PluginManager::m_localInputDeviceTypeID = "sdrangel.samplesource.localinput";
const QString PluginManager::m_remoteInputHardwareID = "RemoteInput";
const QString PluginManager::m_remoteInputDeviceTypeID = "sdrangel.samplesource.remoteinput";
const QString PluginManager::m_fileSourceHardwareID = "FileSource";

Wyświetl plik

@ -103,6 +103,8 @@ private:
PluginAPI::SamplingDeviceRegistrations m_sampleSinkRegistrations; //!< Output sink plugins (one per device kind) register here
// "Local" sample source device IDs
static const QString m_localInputHardwareID; //!< Local input hardware ID
static const QString m_localInputDeviceTypeID; //!< Local input plugin ID
static const QString m_remoteInputHardwareID; //!< Remote input hardware ID
static const QString m_remoteInputDeviceTypeID; //!< Remote input plugin ID
static const QString m_fileSourceHardwareID; //!< FileSource source hardware ID

Wyświetl plik

@ -19,6 +19,7 @@
<file>webapi/doc/swagger/include/FreeDVMod.yaml</file>
<file>webapi/doc/swagger/include/HackRF.yaml</file>
<file>webapi/doc/swagger/include/LimeSdr.yaml</file>
<file>webapi/doc/swagger/include/LocalInput.yaml</file>
<file>webapi/doc/swagger/include/NFMDemod.yaml</file>
<file>webapi/doc/swagger/include/NFMMod.yaml</file>
<file>webapi/doc/swagger/include/Perseus.yaml</file>

Wyświetl plik

@ -1841,6 +1841,9 @@ margin-bottom: 20px;
"NFMModSettings" : {
"$ref" : "#/definitions/NFMModSettings"
},
"LocalSinkSettings" : {
"$ref" : "#/definitions/LocalSinkSettings"
},
"RemoteSinkSettings" : {
"$ref" : "#/definitions/RemoteSinkSettings"
},
@ -2150,6 +2153,9 @@ margin-bottom: 20px;
"limeSdrOutputReport" : {
"$ref" : "#/definitions/LimeSdrOutputReport"
},
"localInputReport" : {
"$ref" : "#/definitions/LocalInputReport"
},
"perseusReport" : {
"$ref" : "#/definitions/PerseusReport"
},
@ -2281,6 +2287,9 @@ margin-bottom: 20px;
"limeSdrOutputSettings" : {
"$ref" : "#/definitions/LimeSdrOutputSettings"
},
"localInputSettings" : {
"$ref" : "#/definitions/LocalInputSettings"
},
"perseusSettings" : {
"$ref" : "#/definitions/PerseusSettings"
},
@ -3213,6 +3222,82 @@ margin-bottom: 20px;
}
},
"description" : "LimeSDR"
};
defs.LocalInputReport = {
"properties" : {
"centerFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"sampleRate" : {
"type" : "integer"
}
},
"description" : "LocalInput"
};
defs.LocalInputSettings = {
"properties" : {
"dcBlock" : {
"type" : "integer"
},
"iqCorrection" : {
"type" : "integer"
},
"fileRecordName" : {
"type" : "string"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
}
},
"description" : "LocalInput"
};
defs.LocalSinkSettings = {
"properties" : {
"localDeviceIndex" : {
"type" : "integer",
"description" : "Receiving local device index"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"log2Decim" : {
"type" : "integer"
},
"filterChainHash" : {
"type" : "integer"
},
"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"
}
},
"description" : "Local channel sink settings"
};
defs.LocationInformation = {
"required" : [ "latitude", "longitude" ],
@ -5765,7 +5850,7 @@ margin-bottom: 20px;
<div id="header">
<div id="api-_">
<h2 id="welcome-to-apidoc">API and SDK Documentation</h2>
<div class="app-desc">Version: 4.5.6</div>
<div class="app-desc">Version: 4.6.0</div>
<hr>
<div><p>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</p>
<hr />
@ -24739,7 +24824,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2019-04-26T13:56:51.976+02:00
Generated 2019-05-01T23:54:36.944+02:00
</div>
</div>
</div>

Wyświetl plik

@ -0,0 +1,27 @@
LocalInputSettings:
description: LocalInput
properties:
dcBlock:
type: integer
iqCorrection:
type: integer
fileRecordName:
type: string
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer
LocalInputReport:
description: LocalInput
properties:
centerFrequency:
type: integer
format: uint64
sampleRate:
type: integer

Wyświetl plik

@ -0,0 +1,25 @@
LocalSinkSettings:
description: "Local channel sink settings"
properties:
localDeviceIndex:
description: "Receiving local device index"
type: integer
rgbColor:
type: integer
title:
type: string
log2Decim:
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

@ -15,7 +15,7 @@ info:
---
version: "4.5.6"
version: "4.6.0"
title: SDRangel
contact:
url: "https://github.com/f4exb/sdrangel"
@ -1806,6 +1806,8 @@ definitions:
$ref: "/doc/swagger/include/LimeSdr.yaml#/LimeSdrInputSettings"
limeSdrOutputSettings:
$ref: "/doc/swagger/include/LimeSdr.yaml#/LimeSdrOutputSettings"
localInputSettings:
$ref: "/doc/swagger/include/LocalInput.yaml#/LocalInputSettings"
perseusSettings:
$ref: "/doc/swagger/include/Perseus.yaml#/PerseusSettings"
plutoSdrInputSettings:
@ -1859,6 +1861,8 @@ definitions:
$ref: "/doc/swagger/include/LimeSdr.yaml#/LimeSdrInputReport"
limeSdrOutputReport:
$ref: "/doc/swagger/include/LimeSdr.yaml#/LimeSdrOutputReport"
localInputReport:
$ref: "/doc/swagger/include/LocalInput.yaml#/LocalInputReport"
perseusReport:
$ref: "/doc/swagger/include/Perseus.yaml#/PerseusReport"
plutoSdrInputReport:
@ -1919,6 +1923,8 @@ definitions:
$ref: "/doc/swagger/include/NFMDemod.yaml#/NFMDemodSettings"
NFMModSettings:
$ref: "/doc/swagger/include/NFMMod.yaml#/NFMModSettings"
LocalSinkSettings:
$ref: "/doc/swagger/include/LocalSink.yaml#/LocalSinkSettings"
RemoteSinkSettings:
$ref: "/doc/swagger/include/RemoteSink.yaml#/RemoteSinkSettings"
RemoteSourceSettings:

Wyświetl plik

@ -2121,6 +2121,21 @@ bool WebAPIRequestMapper::validateDeviceSettings(
return false;
}
}
else if ((*deviceHwType == "LocalInput") && (deviceSettings.getTx() == 0))
{
if (jsonObject.contains("localInputSettings") && jsonObject["localInputSettings"].isObject())
{
QJsonObject localInputSettingsJsonObject = jsonObject["localInputSettings"].toObject();
deviceSettingsKeys = localInputSettingsJsonObject.keys();
deviceSettings.setLocalInputSettings(new SWGSDRangel::SWGLocalInputSettings());
deviceSettings.getLocalInputSettings()->fromJsonObject(localInputSettingsJsonObject);
return true;
}
else
{
return false;
}
}
else if ((*deviceHwType == "RemoteOutput") && (deviceSettings.getTx() != 0))
{
if (jsonObject.contains("remoteOutputSettings") && jsonObject["remoteOutputSettings"].isObject())
@ -2301,6 +2316,20 @@ bool WebAPIRequestMapper::validateChannelSettings(
return false;
}
}
else if (*channelType == "LocalSink")
{
if (channelSettings.getTx() == 0)
{
QJsonObject localChannelSinkSettingsJsonObject = jsonObject["LocalSinkSettings"].toObject();
channelSettingsKeys = localChannelSinkSettingsJsonObject.keys();
channelSettings.setLocalSinkSettings(new SWGSDRangel::SWGLocalSinkSettings());
channelSettings.getLocalSinkSettings()->fromJsonObject(localChannelSinkSettingsJsonObject);
return true;
}
else {
return false;
}
}
else if (*channelType == "RemoteSink")
{
if (channelSettings.getTx() == 0)

Wyświetl plik

@ -1,5 +1,5 @@
name: sdrangel
version: 4.5.6
version: 4.6.0
summary: SDRangel + LimeSDR
description: SDRangel is an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
confinement: strict

Wyświetl plik

@ -0,0 +1,27 @@
LocalInputSettings:
description: LocalInput
properties:
dcBlock:
type: integer
iqCorrection:
type: integer
fileRecordName:
type: string
useReverseAPI:
description: Synchronize with reverse API (1 for yes, 0 for no)
type: integer
reverseAPIAddress:
type: string
reverseAPIPort:
type: integer
reverseAPIDeviceIndex:
type: integer
LocalInputReport:
description: LocalInput
properties:
centerFrequency:
type: integer
format: uint64
sampleRate:
type: integer

Wyświetl plik

@ -0,0 +1,25 @@
LocalSinkSettings:
description: "Local channel sink settings"
properties:
localDeviceIndex:
description: "Receiving local device index"
type: integer
rgbColor:
type: integer
title:
type: string
log2Decim:
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

@ -15,7 +15,7 @@ info:
---
version: "4.5.6"
version: "4.6.0"
title: SDRangel
contact:
url: "https://github.com/f4exb/sdrangel"
@ -1806,6 +1806,8 @@ definitions:
$ref: "http://localhost:8081/api/swagger/include/LimeSdr.yaml#/LimeSdrInputSettings"
limeSdrOutputSettings:
$ref: "http://localhost:8081/api/swagger/include/LimeSdr.yaml#/LimeSdrOutputSettings"
localInputSettings:
$ref: "http://localhost:8081/api/swagger/include/LocalInput.yaml#/LocalInputSettings"
perseusSettings:
$ref: "http://localhost:8081/api/swagger/include/Perseus.yaml#/PerseusSettings"
plutoSdrInputSettings:
@ -1859,6 +1861,8 @@ definitions:
$ref: "http://localhost:8081/api/swagger/include/LimeSdr.yaml#/LimeSdrInputReport"
limeSdrOutputReport:
$ref: "http://localhost:8081/api/swagger/include/LimeSdr.yaml#/LimeSdrOutputReport"
localInputReport:
$ref: "http://localhost:8081/api/swagger/include/LocalInput.yaml#/LocalInputReport"
perseusReport:
$ref: "http://localhost:8081/api/swagger/include/Perseus.yaml#/PerseusReport"
plutoSdrInputReport:
@ -1919,6 +1923,8 @@ definitions:
$ref: "http://localhost:8081/api/swagger/include/NFMDemod.yaml#/NFMDemodSettings"
NFMModSettings:
$ref: "http://localhost:8081/api/swagger/include/NFMMod.yaml#/NFMModSettings"
LocalSinkSettings:
$ref: "http://localhost:8081/api/swagger/include/LocalSink.yaml#/LocalSinkSettings"
RemoteSinkSettings:
$ref: "http://localhost:8081/api/swagger/include/RemoteSink.yaml#/RemoteSinkSettings"
RemoteSourceSettings:

Wyświetl plik

@ -1841,6 +1841,9 @@ margin-bottom: 20px;
"NFMModSettings" : {
"$ref" : "#/definitions/NFMModSettings"
},
"LocalSinkSettings" : {
"$ref" : "#/definitions/LocalSinkSettings"
},
"RemoteSinkSettings" : {
"$ref" : "#/definitions/RemoteSinkSettings"
},
@ -2150,6 +2153,9 @@ margin-bottom: 20px;
"limeSdrOutputReport" : {
"$ref" : "#/definitions/LimeSdrOutputReport"
},
"localInputReport" : {
"$ref" : "#/definitions/LocalInputReport"
},
"perseusReport" : {
"$ref" : "#/definitions/PerseusReport"
},
@ -2281,6 +2287,9 @@ margin-bottom: 20px;
"limeSdrOutputSettings" : {
"$ref" : "#/definitions/LimeSdrOutputSettings"
},
"localInputSettings" : {
"$ref" : "#/definitions/LocalInputSettings"
},
"perseusSettings" : {
"$ref" : "#/definitions/PerseusSettings"
},
@ -3213,6 +3222,82 @@ margin-bottom: 20px;
}
},
"description" : "LimeSDR"
};
defs.LocalInputReport = {
"properties" : {
"centerFrequency" : {
"type" : "integer",
"format" : "uint64"
},
"sampleRate" : {
"type" : "integer"
}
},
"description" : "LocalInput"
};
defs.LocalInputSettings = {
"properties" : {
"dcBlock" : {
"type" : "integer"
},
"iqCorrection" : {
"type" : "integer"
},
"fileRecordName" : {
"type" : "string"
},
"useReverseAPI" : {
"type" : "integer",
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
},
"reverseAPIAddress" : {
"type" : "string"
},
"reverseAPIPort" : {
"type" : "integer"
},
"reverseAPIDeviceIndex" : {
"type" : "integer"
}
},
"description" : "LocalInput"
};
defs.LocalSinkSettings = {
"properties" : {
"localDeviceIndex" : {
"type" : "integer",
"description" : "Receiving local device index"
},
"rgbColor" : {
"type" : "integer"
},
"title" : {
"type" : "string"
},
"log2Decim" : {
"type" : "integer"
},
"filterChainHash" : {
"type" : "integer"
},
"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"
}
},
"description" : "Local channel sink settings"
};
defs.LocationInformation = {
"required" : [ "latitude", "longitude" ],
@ -5765,7 +5850,7 @@ margin-bottom: 20px;
<div id="header">
<div id="api-_">
<h2 id="welcome-to-apidoc">API and SDK Documentation</h2>
<div class="app-desc">Version: 4.5.6</div>
<div class="app-desc">Version: 4.6.0</div>
<hr>
<div><p>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</p>
<hr />
@ -24739,7 +24824,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2019-04-26T13:56:51.976+02:00
Generated 2019-05-01T23:54:36.944+02:00
</div>
</div>
</div>

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Wyświetl plik

@ -2,7 +2,7 @@
* 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.5.6
* OpenAPI spec version: 4.6.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.

Some files were not shown because too many files have changed in this diff Show More