1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 01:55:48 -05:00

Add Android SDR Driver sample source.

This commit is contained in:
Jon Beniston 2023-09-08 10:52:51 +01:00
parent ffbb26c36e
commit 8f00c55ba6
31 changed files with 4725 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -106,3 +106,6 @@ add_subdirectory(audioinput)
add_subdirectory(kiwisdr)
add_subdirectory(remotetcpinput)
add_subdirectory(aaroniartsainput)
if(ANDROID)
add_subdirectory(androidsdrdriverinput)
endif()

View File

@ -0,0 +1,65 @@
project(androidsdrdriverinput)
set(androidsdrdriverinput_SOURCES
androidsdrdriverinputtcphandler.cpp
androidsdrdriverinput.cpp
androidsdrdriverinputsettings.cpp
androidsdrdriverinputwebapiadapter.cpp
androidsdrdriverinputplugin.cpp
)
set(androidsdrdriverinput_HEADERS
androidsdrdriverinputtcphandler.h
androidsdrdriverinput.h
androidsdrdriverinputsettings.h
androidsdrdriverinputwebapiadapter.h
androidsdrdriverinputplugin.h
)
include_directories(
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
)
if(NOT SERVER_MODE)
set(androidsdrdriverinput_SOURCES
${androidsdrdriverinput_SOURCES}
androidsdrdriverinputgui.cpp
androidsdrdriverinputgui.ui
)
set(androidsdrdriverinput_HEADERS
${androidsdrdriverinput_HEADERS}
androidsdrdriverinputgui.h
)
set(TARGET_NAME inputandroidsdrdriverinput)
set(TARGET_LIB "Qt::Widgets")
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()
set(TARGET_NAME inputandroidsdrdriverinputsrv)
set(TARGET_LIB "")
set(TARGET_LIB_GUI "")
set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR})
endif()
add_library(${TARGET_NAME} SHARED
${androidsdrdriverinput_SOURCES}
)
target_link_libraries(${TARGET_NAME}
Qt::Core
${TARGET_LIB}
sdrbase
${TARGET_LIB_GUI}
swagger
)
if(NOT ENABLE_QT6 AND ANDROID)
target_link_libraries(${TARGET_NAME} Qt::AndroidExtras)
endif()
install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER})
# Install debug symbols
if (WIN32)
install(FILES $<TARGET_PDB_FILE:${TARGET_NAME}> CONFIGURATIONS Debug RelWithDebInfo DESTINATION ${INSTALL_FOLDER} )
endif()

View File

@ -0,0 +1,530 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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 <QDesktopServices>
#include <QDebug>
#include <QNetworkReply>
#include <QBuffer>
#include <QJsonParseError>
#include "SWGDeviceSettings.h"
#include "SWGChannelSettings.h"
#include "SWGDeviceState.h"
#include "SWGDeviceReport.h"
#include "SWGAndroidSDRDriverInputReport.h"
#include "util/simpleserializer.h"
#include "util/android.h"
#include "dsp/dspcommands.h"
#include "dsp/dspengine.h"
#include "device/deviceapi.h"
#include "maincore.h"
#include "androidsdrdriverinput.h"
#include "androidsdrdriverinputtcphandler.h"
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput, Message)
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInput::MsgStartStop, Message)
AndroidSDRDriverInput::AndroidSDRDriverInput(DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_settings(),
m_androidSDRDriverInputTCPPHandler(nullptr),
m_deviceDescription("AndroidSDRDriverInput")
{
m_sampleFifo.setLabel(m_deviceDescription);
m_sampleFifo.setSize(48000 * 8);
m_androidSDRDriverInputTCPPHandler = new AndroidSDRDriverInputTCPHandler(&m_sampleFifo, m_deviceAPI);
m_androidSDRDriverInputTCPPHandler->moveToThread(&m_thread);
m_androidSDRDriverInputTCPPHandler->setMessageQueueToInput(&m_inputMessageQueue);
m_deviceAPI->setNbSourceStreams(1);
m_networkManager = new QNetworkAccessManager();
QObject::connect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&AndroidSDRDriverInput::networkManagerFinished
);
}
AndroidSDRDriverInput::~AndroidSDRDriverInput()
{
QObject::disconnect(
m_networkManager,
&QNetworkAccessManager::finished,
this,
&AndroidSDRDriverInput::networkManagerFinished
);
delete m_networkManager;
stop();
m_androidSDRDriverInputTCPPHandler->deleteLater();
}
void AndroidSDRDriverInput::destroy()
{
delete this;
}
void AndroidSDRDriverInput::init()
{
applySettings(m_settings, QList<QString>(), true);
}
void sendIntent()
{
#ifdef ANDROID
Android::sendIntent();
QThread::sleep(2); // FIXME:
#endif
}
bool AndroidSDRDriverInput::start()
{
qDebug() << "AndroidSDRDriverInput::start";
sendIntent();
m_androidSDRDriverInputTCPPHandler->reset();
m_androidSDRDriverInputTCPPHandler->start();
m_androidSDRDriverInputTCPPHandler->getInputMessageQueue()->push(AndroidSDRDriverInputTCPHandler::MsgConfigureTcpHandler::create(m_settings, QList<QString>(), true));
m_thread.start();
return true;
}
void AndroidSDRDriverInput::stop()
{
qDebug() << "AndroidSDRDriverInput::stop";
m_androidSDRDriverInputTCPPHandler->stop();
m_thread.quit();
m_thread.wait();
}
QByteArray AndroidSDRDriverInput::serialize() const
{
return m_settings.serialize();
}
bool AndroidSDRDriverInput::deserialize(const QByteArray& data)
{
bool success = true;
if (!m_settings.deserialize(data))
{
m_settings.resetToDefaults();
success = false;
}
MsgConfigureAndroidSDRDriverInput* message = MsgConfigureAndroidSDRDriverInput::create(m_settings, QList<QString>(), true);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureAndroidSDRDriverInput* messageToGUI = MsgConfigureAndroidSDRDriverInput::create(m_settings, QList<QString>(), true);
m_guiMessageQueue->push(messageToGUI);
}
return success;
}
void AndroidSDRDriverInput::setMessageQueueToGUI(MessageQueue *queue)
{
m_guiMessageQueue = queue;
m_androidSDRDriverInputTCPPHandler->setMessageQueueToGUI(queue);
}
const QString& AndroidSDRDriverInput::getDeviceDescription() const
{
return m_deviceDescription;
}
int AndroidSDRDriverInput::getSampleRate() const
{
return m_settings.m_devSampleRate;
}
quint64 AndroidSDRDriverInput::getCenterFrequency() const
{
return m_settings.m_centerFrequency;
}
void AndroidSDRDriverInput::setCenterFrequency(qint64 centerFrequency)
{
AndroidSDRDriverInputSettings settings = m_settings;
settings.m_centerFrequency = centerFrequency;
MsgConfigureAndroidSDRDriverInput* message = MsgConfigureAndroidSDRDriverInput::create(settings, QList<QString>{"centerFrequency"}, false);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigureAndroidSDRDriverInput* messageToGUI = MsgConfigureAndroidSDRDriverInput::create(settings, QList<QString>{"centerFrequency"}, false);
m_guiMessageQueue->push(messageToGUI);
}
}
bool AndroidSDRDriverInput::handleMessage(const Message& message)
{
if (MsgStartStop::match(message))
{
MsgStartStop& cmd = (MsgStartStop&) message;
qDebug() << "AndroidSDRDriverInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop");
if (cmd.getStartStop())
{
if (m_deviceAPI->initDeviceEngine()) {
m_deviceAPI->startDeviceEngine();
}
}
else
{
m_deviceAPI->stopDeviceEngine();
}
if (m_settings.m_useReverseAPI) {
webapiReverseSendStartStop(cmd.getStartStop());
}
return true;
}
else if (MsgConfigureAndroidSDRDriverInput::match(message))
{
qDebug() << "AndroidSDRDriverInput::handleMessage:" << message.getIdentifier();
MsgConfigureAndroidSDRDriverInput& conf = (MsgConfigureAndroidSDRDriverInput&) message;
applySettings(conf.getSettings(), conf.getSettingsKeys(), conf.getForce());
return true;
}
else if (AndroidSDRDriverInputTCPHandler::MsgReportConnection::match(message))
{
qDebug() << "AndroidSDRDriverInput::handleMessage:" << message.getIdentifier();
AndroidSDRDriverInputTCPHandler::MsgReportConnection& report = (AndroidSDRDriverInputTCPHandler::MsgReportConnection&) message;
if (report.getConnected())
{
qDebug() << "Disconnected - stopping DSP";
m_deviceAPI->stopDeviceEngine();
}
return true;
}
else
{
return false;
}
}
void AndroidSDRDriverInput::applySettings(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force)
{
qDebug() << "AndroidSDRDriverInput::applySettings: force: " << force << settings.getDebugString(settingsKeys, force);
QMutexLocker mutexLocker(&m_mutex);
std::ostringstream os;
bool forwardChange = false;
if (settingsKeys.contains("dcBlock") || settingsKeys.contains("iqCorrection") || force)
{
m_deviceAPI->configureCorrections(settings.m_dcBlock, settings.m_iqCorrection);
qDebug("AndroidSDRDriverInput::applySettings: corrections: DC block: %s IQ imbalance: %s",
settings.m_dcBlock ? "true" : "false",
settings.m_iqCorrection ? "true" : "false");
}
if (settingsKeys.contains("centerFrequency") || force) {
forwardChange = true;
}
if (settingsKeys.contains("devSampleRate") || force) {
forwardChange = true;
}
mutexLocker.unlock();
if (settingsKeys.contains("useReverseAPI"))
{
bool fullUpdate = (settingsKeys.contains("useReverseAPI") && settings.m_useReverseAPI) ||
settingsKeys.contains("reverseAPIAddress") ||
settingsKeys.contains("reverseAPIPort") ||
settingsKeys.contains("reverseAPIDeviceIndex");
webapiReverseSendSettings(settingsKeys, settings, fullUpdate || force);
}
if (forwardChange && (settings.m_devSampleRate != 0))
{
int sampleRate = settings.m_devSampleRate;
DSPSignalNotification *notif = new DSPSignalNotification(sampleRate, settings.m_centerFrequency);
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
m_androidSDRDriverInputTCPPHandler->getInputMessageQueue()->push(AndroidSDRDriverInputTCPHandler::MsgConfigureTcpHandler::create(m_settings, settingsKeys, force));
}
int AndroidSDRDriverInput::webapiRunGet(
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage)
{
(void) errorMessage;
m_deviceAPI->getDeviceEngineStateStr(*response.getState());
return 200;
}
int AndroidSDRDriverInput::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 AndroidSDRDriverInput::webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAndroidSdrDriverInputSettings(new SWGSDRangel::SWGAndroidSDRDriverInputSettings());
response.getAndroidSdrDriverInputSettings()->init();
webapiFormatDeviceSettings(response, m_settings);
return 200;
}
int AndroidSDRDriverInput::webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage)
{
(void) errorMessage;
AndroidSDRDriverInputSettings settings = m_settings;
webapiUpdateDeviceSettings(settings, deviceSettingsKeys, response);
MsgConfigureAndroidSDRDriverInput *msg = MsgConfigureAndroidSDRDriverInput::create(settings, deviceSettingsKeys, force);
m_inputMessageQueue.push(msg);
if (m_guiMessageQueue) // forward to GUI if any
{
MsgConfigureAndroidSDRDriverInput *msgToGUI = MsgConfigureAndroidSDRDriverInput::create(settings, deviceSettingsKeys, force);
m_guiMessageQueue->push(msgToGUI);
}
webapiFormatDeviceSettings(response, settings);
return 200;
}
void AndroidSDRDriverInput::webapiUpdateDeviceSettings(
AndroidSDRDriverInputSettings& settings,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response)
{
if (deviceSettingsKeys.contains("centerFrequency")) {
settings.m_centerFrequency = response.getAndroidSdrDriverInputSettings()->getCenterFrequency();
}
if (deviceSettingsKeys.contains("loPpmCorrection")) {
settings.m_loPpmCorrection = response.getAndroidSdrDriverInputSettings()->getLoPpmCorrection();
}
if (deviceSettingsKeys.contains("dcBlock")) {
settings.m_dcBlock = response.getAndroidSdrDriverInputSettings()->getDcBlock() != 0;
}
if (deviceSettingsKeys.contains("iqCorrection")) {
settings.m_iqCorrection = response.getAndroidSdrDriverInputSettings()->getIqCorrection() != 0;
}
if (deviceSettingsKeys.contains("biasTee")) {
settings.m_biasTee = response.getAndroidSdrDriverInputSettings()->getBiasTee() != 0;
}
if (deviceSettingsKeys.contains("directSampling")) {
settings.m_directSampling = response.getAndroidSdrDriverInputSettings()->getDirectSampling() != 0;
}
if (deviceSettingsKeys.contains("devSampleRate")) {
settings.m_devSampleRate = response.getAndroidSdrDriverInputSettings()->getDevSampleRate();
}
if (deviceSettingsKeys.contains("agc")) {
settings.m_agc = response.getAndroidSdrDriverInputSettings()->getAgc() != 0;
}
if (deviceSettingsKeys.contains("rfBW")) {
settings.m_rfBW = response.getAndroidSdrDriverInputSettings()->getRfBw();
}
if (deviceSettingsKeys.contains("sampleBits")) {
settings.m_sampleBits = response.getAndroidSdrDriverInputSettings()->getSampleBits();
}
if (deviceSettingsKeys.contains("dataPort")) {
settings.m_dataPort = response.getAndroidSdrDriverInputSettings()->getDataPort();
}
if (deviceSettingsKeys.contains("useReverseAPI")) {
settings.m_useReverseAPI = response.getAndroidSdrDriverInputSettings()->getUseReverseApi() != 0;
}
if (deviceSettingsKeys.contains("reverseAPIAddress")) {
settings.m_reverseAPIAddress = *response.getAndroidSdrDriverInputSettings()->getReverseApiAddress();
}
if (deviceSettingsKeys.contains("reverseAPIPort")) {
settings.m_reverseAPIPort = response.getAndroidSdrDriverInputSettings()->getReverseApiPort();
}
if (deviceSettingsKeys.contains("reverseAPIDeviceIndex")) {
settings.m_reverseAPIDeviceIndex = response.getAndroidSdrDriverInputSettings()->getReverseApiDeviceIndex();
}
}
void AndroidSDRDriverInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const AndroidSDRDriverInputSettings& settings)
{
response.getAndroidSdrDriverInputSettings()->setCenterFrequency(settings.m_centerFrequency);
response.getAndroidSdrDriverInputSettings()->setLoPpmCorrection(settings.m_loPpmCorrection);
response.getAndroidSdrDriverInputSettings()->setDcBlock(settings.m_dcBlock ? 1 : 0);
response.getAndroidSdrDriverInputSettings()->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
response.getAndroidSdrDriverInputSettings()->setBiasTee(settings.m_biasTee ? 1 : 0);
response.getAndroidSdrDriverInputSettings()->setDirectSampling(settings.m_directSampling ? 1 : 0);
response.getAndroidSdrDriverInputSettings()->setDevSampleRate(settings.m_devSampleRate);
response.getAndroidSdrDriverInputSettings()->setGain(settings.m_gain[0]);
response.getAndroidSdrDriverInputSettings()->setAgc(settings.m_agc ? 1 : 0);
response.getAndroidSdrDriverInputSettings()->setRfBw(settings.m_rfBW);
response.getAndroidSdrDriverInputSettings()->setSampleBits(settings.m_sampleBits);
response.getAndroidSdrDriverInputSettings()->setDataPort(settings.m_dataPort);
response.getAndroidSdrDriverInputSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
if (response.getAndroidSdrDriverInputSettings()->getReverseApiAddress()) {
*response.getAndroidSdrDriverInputSettings()->getReverseApiAddress() = settings.m_reverseAPIAddress;
} else {
response.getAndroidSdrDriverInputSettings()->setReverseApiAddress(new QString(settings.m_reverseAPIAddress));
}
response.getAndroidSdrDriverInputSettings()->setReverseApiPort(settings.m_reverseAPIPort);
response.getAndroidSdrDriverInputSettings()->setReverseApiDeviceIndex(settings.m_reverseAPIDeviceIndex);
}
int AndroidSDRDriverInput::webapiReportGet(
SWGSDRangel::SWGDeviceReport& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAndroidSdrDriverInputReport(new SWGSDRangel::SWGAndroidSDRDriverInputReport());
response.getAndroidSdrDriverInputReport()->init();
webapiFormatDeviceReport(response);
return 200;
}
void AndroidSDRDriverInput::webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response)
{
response.getAndroidSdrDriverInputReport()->setSampleRate(m_settings.m_devSampleRate);
}
void AndroidSDRDriverInput::webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const AndroidSDRDriverInputSettings& settings, bool force)
{
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
swgDeviceSettings->setDirection(0); // single Rx
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
swgDeviceSettings->setDeviceHwType(new QString("AndroidSDRDriverInput"));
swgDeviceSettings->setAndroidSdrDriverInputSettings(new SWGSDRangel::SWGAndroidSDRDriverInputSettings());
SWGSDRangel::SWGAndroidSDRDriverInputSettings *swgAndroidSDRDriverInputSettings = swgDeviceSettings->getAndroidSdrDriverInputSettings();
// transfer data that has been modified. When force is on transfer all data except reverse API data
if (deviceSettingsKeys.contains("dcBlock") || force) {
swgAndroidSDRDriverInputSettings->setDcBlock(settings.m_dcBlock ? 1 : 0);
}
if (deviceSettingsKeys.contains("iqCorrection") || force) {
swgAndroidSDRDriverInputSettings->setIqCorrection(settings.m_iqCorrection ? 1 : 0);
}
if (deviceSettingsKeys.contains("biasTee") || force) {
swgAndroidSDRDriverInputSettings->setBiasTee(settings.m_biasTee ? 1 : 0);
}
if (deviceSettingsKeys.contains("dataPort") || force) {
swgAndroidSDRDriverInputSettings->setDataPort(settings.m_dataPort);
}
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
QNetworkReply *reply = m_networkManager->sendCustomRequest(m_networkRequest, "PATCH", buffer);
buffer->setParent(reply);
delete swgDeviceSettings;
}
void AndroidSDRDriverInput::webapiReverseSendStartStop(bool start)
{
SWGSDRangel::SWGDeviceSettings *swgDeviceSettings = new SWGSDRangel::SWGDeviceSettings();
swgDeviceSettings->setDirection(0); // single Rx
swgDeviceSettings->setOriginatorIndex(m_deviceAPI->getDeviceSetIndex());
swgDeviceSettings->setDeviceHwType(new QString("AndroidSDRDriverInput"));
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);
QNetworkReply *reply;
if (start) {
reply = m_networkManager->sendCustomRequest(m_networkRequest, "POST", buffer);
} else {
reply = m_networkManager->sendCustomRequest(m_networkRequest, "DELETE", buffer);
}
buffer->setParent(reply);
delete swgDeviceSettings;
}
void AndroidSDRDriverInput::networkManagerFinished(QNetworkReply *reply)
{
QNetworkReply::NetworkError replyError = reply->error();
if (replyError)
{
qWarning() << "AndroidSDRDriverInput::networkManagerFinished:"
<< " error(" << (int) replyError
<< "): " << replyError
<< ": " << reply->errorString();
}
else
{
QString answer = reply->readAll();
answer.chop(1); // remove last \n
qDebug("AndroidSDRDriverInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
}
reply->deleteLater();
}

View File

@ -0,0 +1,161 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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_ANDROIDSDRDRIVERINPUT_H
#define INCLUDE_ANDROIDSDRDRIVERINPUT_H
#include <ctime>
#include <iostream>
#include <stdint.h>
#include <QString>
#include <QByteArray>
#include <QTimer>
#include <QThread>
#include <QNetworkRequest>
#include "dsp/devicesamplesource.h"
#include "androidsdrdriverinputsettings.h"
class QNetworkAccessManager;
class QNetworkReply;
class DeviceAPI;
class AndroidSDRDriverInputTCPHandler;
class AndroidSDRDriverInput : public DeviceSampleSource {
Q_OBJECT
public:
class MsgConfigureAndroidSDRDriverInput : public Message {
MESSAGE_CLASS_DECLARATION
public:
const AndroidSDRDriverInputSettings& getSettings() const { return m_settings; }
const QList<QString>& getSettingsKeys() const { return m_settingsKeys; }
bool getForce() const { return m_force; }
static MsgConfigureAndroidSDRDriverInput* create(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force = false) {
return new MsgConfigureAndroidSDRDriverInput(settings, settingsKeys, force);
}
private:
AndroidSDRDriverInputSettings m_settings;
QList<QString> m_settingsKeys;
bool m_force;
MsgConfigureAndroidSDRDriverInput(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force) :
Message(),
m_settings(settings),
m_settingsKeys(settingsKeys),
m_force(force)
{ }
};
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)
{ }
};
AndroidSDRDriverInput(DeviceAPI *deviceAPI);
virtual ~AndroidSDRDriverInput();
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) { (void) 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);
static void webapiFormatDeviceSettings(
SWGSDRangel::SWGDeviceSettings& response,
const AndroidSDRDriverInputSettings& settings);
static void webapiUpdateDeviceSettings(
AndroidSDRDriverInputSettings& settings,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response);
private:
DeviceAPI *m_deviceAPI;
QRecursiveMutex m_mutex;
AndroidSDRDriverInputSettings m_settings;
AndroidSDRDriverInputTCPHandler* m_androidSDRDriverInputTCPPHandler;
QString m_deviceDescription;
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
QThread m_thread;
void applySettings(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force = false);
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport& response);
void webapiReverseSendSettings(const QList<QString>& deviceSettingsKeys, const AndroidSDRDriverInputSettings& settings, bool force);
void webapiReverseSendStartStop(bool start);
private slots:
void networkManagerFinished(QNetworkReply *reply);
};
#endif // INCLUDE_ANDROIDSDRDRIVERINPUT_H

View File

@ -0,0 +1,599 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QDebug>
#include <QMessageBox>
#include <QDateTime>
#include <QString>
#include "ui_androidsdrdriverinputgui.h"
#include "gui/colormapper.h"
#include "gui/glspectrum.h"
#include "gui/basicdevicesettingsdialog.h"
#include "gui/dialogpositioner.h"
#include "dsp/dspengine.h"
#include "dsp/dspcommands.h"
#include "dsp/hbfilterchainconverter.h"
#include "mainwindow.h"
#include "util/simpleserializer.h"
#include "device/deviceapi.h"
#include "device/deviceuiset.h"
#include "androidsdrdriverinputgui.h"
#include "androidsdrdriverinputtcphandler.h"
AndroidSDRDriverInputGui::AndroidSDRDriverInputGui(DeviceUISet *deviceUISet, QWidget* parent) :
DeviceGUI(parent),
ui(new Ui::AndroidSDRDriverInputGui),
m_settings(),
m_sampleSource(0),
m_lastEngineState(DeviceAPI::StNotStarted),
m_sampleRate(0),
m_centerFrequency(0),
m_doApplySettings(true),
m_forceSettings(true),
m_deviceGains(nullptr),
m_remoteDevice(RemoteTCPProtocol::RTLSDR_R820T),
m_connectionError(false)
{
m_deviceUISet = deviceUISet;
setAttribute(Qt::WA_DeleteOnClose, true);
ui->setupUi(getContents());
sizeToContents();
getContents()->setStyleSheet("#AndroidSDRDriverInputGui { background-color: rgb(64, 64, 64); }");
m_helpURL = "plugins/samplesource/androidsdrdriverinput/readme.md";
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->centerFrequency->setValueRange(9, 0, 999999999); // frequency dial is in kHz
ui->devSampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
ui->devSampleRate->setValueRange(8, 0, 99999999);
ui->rfBW->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow));
ui->rfBW->setValueRange(5, 0, 99999); // In kHz
connect(this, SIGNAL(customContextMenuRequested(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 = (AndroidSDRDriverInput*) m_deviceUISet->m_deviceAPI->getSampleSource();
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection);
m_sampleSource->setMessageQueueToGUI(&m_inputMessageQueue);
m_forceSettings = true;
sendSettings();
makeUIConnections();
}
AndroidSDRDriverInputGui::~AndroidSDRDriverInputGui()
{
m_statusTimer.stop();
m_updateTimer.stop();
delete ui;
}
void AndroidSDRDriverInputGui::blockApplySettings(bool block)
{
m_doApplySettings = !block;
}
void AndroidSDRDriverInputGui::destroy()
{
delete this;
}
void AndroidSDRDriverInputGui::resetToDefaults()
{
m_settings.resetToDefaults();
displaySettings();
m_forceSettings = true;
sendSettings();
}
QByteArray AndroidSDRDriverInputGui::serialize() const
{
return m_settings.serialize();
}
bool AndroidSDRDriverInputGui::deserialize(const QByteArray& data)
{
qDebug("AndroidSDRDriverInputGui::deserialize");
if (m_settings.deserialize(data))
{
displaySettings();
m_forceSettings = true;
sendSettings();
return true;
}
else
{
return false;
}
}
bool AndroidSDRDriverInputGui::handleMessage(const Message& message)
{
if (AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::match(message))
{
const AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput& cfg = (AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput&) message;
if (cfg.getForce()) {
m_settings = cfg.getSettings();
} else {
m_settings.applySettings(cfg.getSettingsKeys(), cfg.getSettings());
}
blockApplySettings(true);
displaySettings();
blockApplySettings(false);
return true;
}
else if (AndroidSDRDriverInput::MsgStartStop::match(message))
{
AndroidSDRDriverInput::MsgStartStop& notif = (AndroidSDRDriverInput::MsgStartStop&) message;
m_connectionError = false;
blockApplySettings(true);
ui->startStop->setChecked(notif.getStartStop());
blockApplySettings(false);
return true;
}
else if (AndroidSDRDriverInputTCPHandler::MsgReportRemoteDevice::match(message))
{
const AndroidSDRDriverInputTCPHandler::MsgReportRemoteDevice& report = (AndroidSDRDriverInputTCPHandler::MsgReportRemoteDevice&) message;
QHash<RemoteTCPProtocol::Device, QString> devices = {
{RemoteTCPProtocol::RTLSDR_E4000, "RTLSDR E4000"},
{RemoteTCPProtocol::RTLSDR_FC0012, "RTLSDR FC0012"},
{RemoteTCPProtocol::RTLSDR_FC0013, "RTLSDR FC0013"},
{RemoteTCPProtocol::RTLSDR_FC2580, "RTLSDR FC2580"},
{RemoteTCPProtocol::RTLSDR_R820T, "RTLSDR R820T"},
{RemoteTCPProtocol::RTLSDR_R828D, "RTLSDR R828D"},
{RemoteTCPProtocol::HACK_RF, "HackRF"},
{RemoteTCPProtocol::SDRPLAY_V3_RSPDUO, "SDRplay"}, // MIR0 protocol doesn't distinguish between devices - AndroidSDRDriverInputTCPHandler::dataReadyRead always sends SDRPLAY_V3_RSPDUO
};
QString device = "Unknown";
m_remoteDevice = report.getDevice();
if (devices.contains(m_remoteDevice)) {
device = devices.value(m_remoteDevice);
}
// Update GUI so we only show widgets available for the protocol in use
bool mir0 = report.getProtocol() == "MIR0";
if (mir0 && (ui->sampleBits->count() != 2))
{
ui->sampleBits->addItem("16");
}
else if (!mir0 && (ui->sampleBits->count() != 1))
{
while (ui->sampleBits->count() > 1) {
ui->sampleBits->removeItem(ui->sampleBits->count() - 1);
}
}
ui->centerFrequency->setValueRange(7, 0, 9999999);
displayGains();
setStatus(device);
return true;
}
else if (AndroidSDRDriverInputTCPHandler::MsgReportConnection::match(message))
{
const AndroidSDRDriverInputTCPHandler::MsgReportConnection& report = (AndroidSDRDriverInputTCPHandler::MsgReportConnection&) message;
qDebug() << "AndroidSDRDriverInputGui::handleMessage: MsgReportConnection connected: " << report.getConnected();
if (report.getConnected())
{
m_connectionError = false;
ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
}
else
{
m_connectionError = true;
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
}
return true;
}
else
{
return false;
}
}
void AndroidSDRDriverInputGui::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (DSPSignalNotification::match(*message))
{
DSPSignalNotification* notif = (DSPSignalNotification*) message;
m_sampleRate = notif->getSampleRate();
m_centerFrequency = notif->getCenterFrequency();
qDebug("AndroidSDRDriverInputGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency());
updateSampleRateAndFrequency();
delete message;
}
else
{
if (handleMessage(*message))
{
delete message;
}
}
}
}
void AndroidSDRDriverInputGui::updateSampleRateAndFrequency()
{
m_deviceUISet->getSpectrum()->setSampleRate(m_sampleRate);
m_deviceUISet->getSpectrum()->setCenterFrequency(m_centerFrequency);
ui->deviceRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000));
}
void AndroidSDRDriverInputGui::displaySettings()
{
blockApplySettings(true);
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
ui->ppm->setValue(m_settings.m_loPpmCorrection);
ui->dcOffset->setChecked(m_settings.m_dcBlock);
ui->iqImbalance->setChecked(m_settings.m_iqCorrection);
ui->biasTee->setChecked(m_settings.m_biasTee);
ui->directSampling->setChecked(m_settings.m_directSampling);
ui->devSampleRate->setValue(m_settings.m_devSampleRate);
ui->agc->setChecked(m_settings.m_agc);
ui->rfBW->setValue(m_settings.m_rfBW / 1000);
ui->deviceRateText->setText(tr("%1k").arg(m_settings.m_devSampleRate / 1000.0));
ui->sampleBits->setCurrentIndex(m_settings.m_sampleBits/8-1);
ui->dataPort->setText(tr("%1").arg(m_settings.m_dataPort));
displayGains();
blockApplySettings(false);
}
const AndroidSDRDriverInputGui::DeviceGains::GainRange AndroidSDRDriverInputGui::m_rtlSDR34kGainRange(
"Gain",
{
-10, 15, 40, 65, 90, 115, 140, 165, 190, 215,
240, 290, 340, 420
}
);
const AndroidSDRDriverInputGui::DeviceGains AndroidSDRDriverInputGui::m_rtlSDRe4kGains({AndroidSDRDriverInputGui::m_rtlSDR34kGainRange}, true, false);
const AndroidSDRDriverInputGui::DeviceGains::GainRange AndroidSDRDriverInputGui::m_rtlSDRR820GainRange(
"Gain",
{
0, 9, 14, 27, 37, 77, 87, 125, 144, 157,
166, 197, 207, 229, 254, 280, 297, 328,
338, 364, 372, 386, 402, 421, 434, 439,
445, 480, 496
}
);
const AndroidSDRDriverInputGui::DeviceGains AndroidSDRDriverInputGui::m_rtlSDRR820Gains({AndroidSDRDriverInputGui::m_rtlSDRR820GainRange}, true, true);
const AndroidSDRDriverInputGui::DeviceGains::GainRange AndroidSDRDriverInputGui::m_hackRFLNAGainRange("LNA", 0, 40, 8);
const AndroidSDRDriverInputGui::DeviceGains::GainRange AndroidSDRDriverInputGui::m_hackRFVGAGainRange("VGA", 0, 62, 2);
const AndroidSDRDriverInputGui::DeviceGains AndroidSDRDriverInputGui::m_hackRFGains({m_hackRFLNAGainRange, m_hackRFVGAGainRange}, false, true);
// SDRplay LNA gain is device & frequency dependent (See sdrplayv3input.h SDRPlayV3LNA)
const AndroidSDRDriverInputGui::DeviceGains::GainRange AndroidSDRDriverInputGui::m_sdrplayV3LNAGainRange("LNA", 0, 9, 1, "");
const AndroidSDRDriverInputGui::DeviceGains::GainRange AndroidSDRDriverInputGui::m_sdrplayV3IFGainRange("IF", -59, -20, 1);
const AndroidSDRDriverInputGui::DeviceGains AndroidSDRDriverInputGui::m_sdrplayV3Gains({m_sdrplayV3LNAGainRange, m_sdrplayV3IFGainRange}, true, true);
const QHash<RemoteTCPProtocol::Device, const AndroidSDRDriverInputGui::DeviceGains *> AndroidSDRDriverInputGui::m_gains =
{
{RemoteTCPProtocol::RTLSDR_E4000, &m_rtlSDRe4kGains},
{RemoteTCPProtocol::RTLSDR_R820T, &m_rtlSDRR820Gains},
{RemoteTCPProtocol::HACK_RF, &m_hackRFGains},
{RemoteTCPProtocol::SDRPLAY_V3_RSP1, &m_sdrplayV3Gains},
{RemoteTCPProtocol::SDRPLAY_V3_RSP1A, &m_sdrplayV3Gains},
{RemoteTCPProtocol::SDRPLAY_V3_RSP2, &m_sdrplayV3Gains},
{RemoteTCPProtocol::SDRPLAY_V3_RSPDUO, &m_sdrplayV3Gains},
{RemoteTCPProtocol::SDRPLAY_V3_RSPDX, &m_sdrplayV3Gains},
};
QString AndroidSDRDriverInputGui::gainText(int stage)
{
if (m_deviceGains) {
return QString("%1.%2%3").arg(m_settings.m_gain[stage] / 10).arg(abs(m_settings.m_gain[stage] % 10)).arg(m_deviceGains->m_gains[stage].m_units);
} else {
return "";
}
}
void AndroidSDRDriverInputGui::displayGains()
{
QLabel *gainLabels[] = {ui->gain1Label, ui->gain2Label};
QSlider *gain[] = {ui->gain1, ui->gain2};
QLabel *gainTexts[] = {ui->gain1Text, ui->gain2Text};
QWidget *gainLine[] = {ui->gainLine1};
m_deviceGains = m_gains.value(m_remoteDevice);
if (m_deviceGains)
{
ui->agc->setVisible(m_deviceGains->m_agc);
ui->biasTee->setVisible(m_deviceGains->m_biasTee);
ui->directSampling->setVisible(m_remoteDevice <= RemoteTCPProtocol::RTLSDR_R828D);
for (int i = 0; i < 2; i++)
{
bool visible = i < m_deviceGains->m_gains.size();
gainLabels[i]->setVisible(visible);
gain[i]->setVisible(visible);
gainTexts[i]->setVisible(visible);
if (i > 0) {
gainLine[i-1]->setVisible(visible);
}
if (visible)
{
gainLabels[i]->setText(m_deviceGains->m_gains[i].m_name);
gain[i]->blockSignals(true);
if (m_deviceGains->m_gains[i].m_gains.size() > 0)
{
gain[i]->setMinimum(0);
gain[i]->setMaximum(m_deviceGains->m_gains[i].m_gains.size() - 1);
gain[i]->setSingleStep(1);
gain[i]->setPageStep(1);
}
else
{
gain[i]->setMinimum(m_deviceGains->m_gains[i].m_min);
gain[i]->setMaximum(m_deviceGains->m_gains[i].m_max);
gain[i]->setSingleStep(m_deviceGains->m_gains[i].m_step);
gain[i]->setPageStep(m_deviceGains->m_gains[i].m_step);
}
if (m_deviceGains->m_gains[i].m_gains.size() > 0) {
gain[i]->setValue(m_deviceGains->m_gains[i].m_gains.indexOf(m_settings.m_gain[i]));
} else {
gain[i]->setValue(m_settings.m_gain[i] / 10);
}
gain[i]->blockSignals(false);
gainTexts[i]->setText(gainText(i));
}
}
}
else
{
qDebug() << "AndroidSDRDriverInputGui::displayGains: No gains for " << m_remoteDevice;
}
}
void AndroidSDRDriverInputGui::sendSettings()
{
if (!m_updateTimer.isActive()) {
m_updateTimer.start(100);
}
}
void AndroidSDRDriverInputGui::on_startStop_toggled(bool checked)
{
if (m_doApplySettings)
{
m_connectionError = false;
AndroidSDRDriverInput::MsgStartStop *message = AndroidSDRDriverInput::MsgStartStop::create(checked);
m_sampleSource->getInputMessageQueue()->push(message);
}
}
void AndroidSDRDriverInputGui::on_centerFrequency_changed(quint64 value)
{
m_settings.m_centerFrequency = value * 1000;
m_settingsKeys.append("centerFrequency");
sendSettings();
}
void AndroidSDRDriverInputGui::on_devSampleRate_changed(quint64 value)
{
m_settings.m_devSampleRate = value;
m_settingsKeys.append("devSampleRate");
sendSettings();
}
void AndroidSDRDriverInputGui::on_ppm_valueChanged(int value)
{
m_settings.m_loPpmCorrection = value;
ui->ppmText->setText(tr("%1").arg(value));
m_settingsKeys.append("loPpmCorrection");
sendSettings();
}
void AndroidSDRDriverInputGui::on_dcOffset_toggled(bool checked)
{
m_settings.m_dcBlock = checked;
m_settingsKeys.append("dcBlock");
sendSettings();
}
void AndroidSDRDriverInputGui::on_iqImbalance_toggled(bool checked)
{
m_settings.m_iqCorrection = checked;
m_settingsKeys.append("iqCorrection");
sendSettings();
}
void AndroidSDRDriverInputGui::on_biasTee_toggled(bool checked)
{
m_settings.m_biasTee = checked;
m_settingsKeys.append("biasTee");
sendSettings();
}
void AndroidSDRDriverInputGui::on_directSampling_toggled(bool checked)
{
m_settings.m_directSampling = checked;
m_settingsKeys.append("directSampling");
sendSettings();
}
void AndroidSDRDriverInputGui::on_agc_toggled(bool checked)
{
m_settings.m_agc = checked;
m_settingsKeys.append("agc");
sendSettings();
}
void AndroidSDRDriverInputGui::on_gain1_valueChanged(int value)
{
if (m_deviceGains && (m_deviceGains->m_gains.size() >= 1) && (m_deviceGains->m_gains[0].m_gains.size() > 0)) {
m_settings.m_gain[0] = m_deviceGains->m_gains[0].m_gains[value];
} else {
m_settings.m_gain[0] = value * 10;
}
ui->gain1Text->setText(gainText(0));
m_settingsKeys.append("gain[0]");
sendSettings();
}
void AndroidSDRDriverInputGui::on_gain2_valueChanged(int value)
{
if (m_deviceGains && (m_deviceGains->m_gains.size() >= 2) && (m_deviceGains->m_gains[1].m_gains.size() > 0)) {
m_settings.m_gain[1] = m_deviceGains->m_gains[1].m_gains[value];
} else {
m_settings.m_gain[1] = value * 10;
}
ui->gain2Text->setText(gainText(1));
m_settingsKeys.append("gain[1]");
sendSettings();
}
void AndroidSDRDriverInputGui::on_rfBW_changed(int value)
{
m_settings.m_rfBW = value * 1000;
m_settingsKeys.append("rfBW");
sendSettings();
}
void AndroidSDRDriverInputGui::on_sampleBits_currentIndexChanged(int index)
{
m_settings.m_sampleBits = 8 * (index + 1);
m_settingsKeys.append("sampleBits");
sendSettings();
}
void AndroidSDRDriverInputGui::on_dataPort_editingFinished()
{
bool ok;
quint16 udpPort = ui->dataPort->text().toInt(&ok);
if ((!ok) || (udpPort < 1024)) {
udpPort = 9998;
}
m_settings.m_dataPort = udpPort;
ui->dataPort->setText(tr("%1").arg(m_settings.m_dataPort));
m_settingsKeys.append("dataPort");
sendSettings();
}
void AndroidSDRDriverInputGui::updateHardware()
{
if (m_doApplySettings)
{
qDebug() << "AndroidSDRDriverInputGui::updateHardware";
AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput* message =
AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(m_settings, m_settingsKeys, m_forceSettings);
m_sampleSource->getInputMessageQueue()->push(message);
m_forceSettings = false;
m_settingsKeys.clear();
m_updateTimer.stop();
}
}
void AndroidSDRDriverInputGui::updateStatus()
{
int state = m_deviceUISet->m_deviceAPI->state();
if (!m_connectionError && (m_lastEngineState != state))
{
switch(state)
{
case DeviceAPI::StNotStarted:
ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }");
break;
case DeviceAPI::StIdle:
ui->startStop->setStyleSheet("QToolButton { background-color : blue; }");
break;
case DeviceAPI::StRunning:
ui->startStop->setStyleSheet("QToolButton { background-color : green; }");
break;
case DeviceAPI::StError:
ui->startStop->setStyleSheet("QToolButton { background-color : red; }");
QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage());
break;
default:
break;
}
m_lastEngineState = state;
}
}
void AndroidSDRDriverInputGui::openDeviceSettingsDialog(const QPoint& p)
{
if (m_contextMenuType == ContextMenuDeviceSettings)
{
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);
new DialogPositioner(&dialog, false);
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();
}
resetContextMenuType();
}
void AndroidSDRDriverInputGui::makeUIConnections()
{
QObject::connect(ui->startStop, &ButtonSwitch::toggled, this, &AndroidSDRDriverInputGui::on_startStop_toggled);
QObject::connect(ui->centerFrequency, &ValueDial::changed, this, &AndroidSDRDriverInputGui::on_centerFrequency_changed);
QObject::connect(ui->ppm, &QSlider::valueChanged, this, &AndroidSDRDriverInputGui::on_ppm_valueChanged);
QObject::connect(ui->dcOffset, &ButtonSwitch::toggled, this, &AndroidSDRDriverInputGui::on_dcOffset_toggled);
QObject::connect(ui->iqImbalance, &ButtonSwitch::toggled, this, &AndroidSDRDriverInputGui::on_iqImbalance_toggled);
QObject::connect(ui->biasTee, &ButtonSwitch::toggled, this, &AndroidSDRDriverInputGui::on_biasTee_toggled);
QObject::connect(ui->directSampling, &ButtonSwitch::toggled, this, &AndroidSDRDriverInputGui::on_directSampling_toggled);
QObject::connect(ui->devSampleRate, &ValueDial::changed, this, &AndroidSDRDriverInputGui::on_devSampleRate_changed);
QObject::connect(ui->gain1, &QSlider::valueChanged, this, &AndroidSDRDriverInputGui::on_gain1_valueChanged);
QObject::connect(ui->gain2, &QSlider::valueChanged, this, &AndroidSDRDriverInputGui::on_gain2_valueChanged);
QObject::connect(ui->agc, &ButtonSwitch::toggled, this, &AndroidSDRDriverInputGui::on_agc_toggled);
QObject::connect(ui->rfBW, &ValueDial::changed, this, &AndroidSDRDriverInputGui::on_rfBW_changed);
QObject::connect(ui->sampleBits, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &AndroidSDRDriverInputGui::on_sampleBits_currentIndexChanged);
QObject::connect(ui->dataPort, &QLineEdit::editingFinished, this, &AndroidSDRDriverInputGui::on_dataPort_editingFinished);
}

View File

@ -0,0 +1,187 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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_ANDROIDSDRDRIVERINPUTGUI_H
#define INCLUDE_ANDROIDSDRDRIVERINPUTGUI_H
#include <QTimer>
#include <QElapsedTimer>
#include <QWidget>
#include "device/devicegui.h"
#include "util/messagequeue.h"
#include "androidsdrdriverinput.h"
#include "../../channelrx/remotetcpsink/remotetcpprotocol.h"
class DeviceUISet;
class QNetworkAccessManager;
class QNetworkReply;
class QJsonObject;
namespace Ui {
class AndroidSDRDriverInputGui;
}
class AndroidSDRDriverInputGui : public DeviceGUI {
Q_OBJECT
struct DeviceGains {
struct GainRange {
QString m_name;
int m_min;
int m_max;
int m_step; // In dB
QVector<int> m_gains; // In 10ths of dB
QString m_units; // Units label for display in the GUI
GainRange(const QString& name, int min, int max, int step, const QString& units = "dB") :
m_name(name),
m_min(min),
m_max(max),
m_step(step),
m_units(units)
{
}
GainRange(const QString& name, QVector<int> gains, const QString& units = "dB") :
m_name(name),
m_min(0),
m_max(0),
m_step(0),
m_gains(gains),
m_units(units)
{
}
};
DeviceGains()
{
}
DeviceGains(QList<GainRange> gains, bool agc, bool biasTee) :
m_gains(gains),
m_agc(agc),
m_biasTee(biasTee)
{
}
QList<GainRange> m_gains;
bool m_agc;
bool m_biasTee;
};
public:
explicit AndroidSDRDriverInputGui(DeviceUISet *deviceUISet, QWidget* parent = 0);
virtual ~AndroidSDRDriverInputGui();
virtual void destroy();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
private:
Ui::AndroidSDRDriverInputGui* ui;
AndroidSDRDriverInputSettings m_settings; //!< current settings
QList<QString> m_settingsKeys;
AndroidSDRDriverInput* m_sampleSource;
QTimer m_updateTimer;
QTimer m_statusTimer;
int m_lastEngineState;
MessageQueue m_inputMessageQueue;
int m_sampleRate;
quint64 m_centerFrequency;
bool m_doApplySettings;
bool m_forceSettings;
const DeviceGains *m_deviceGains;
RemoteTCPProtocol::Device m_remoteDevice; // Remote device reported when connecting
bool m_connectionError;
static const DeviceGains::GainRange m_rtlSDR34kGainRange;
static const DeviceGains m_rtlSDRe4kGains;
static const DeviceGains::GainRange m_rtlSDRR820GainRange;
static const DeviceGains m_rtlSDRR820Gains;
static const DeviceGains::GainRange m_airspyLNAGainRange;
static const DeviceGains::GainRange m_airspyMixerGainRange;
static const DeviceGains::GainRange m_airspyVGAGainRange;
static const DeviceGains m_airspyGains;
static const DeviceGains::GainRange m_airspyHFAttRange;
static const DeviceGains m_airspyHFGains;
static const DeviceGains::GainRange m_bladeRF1LNARange;
static const DeviceGains::GainRange m_bladeRF1VGA1Range;
static const DeviceGains::GainRange m_bladeRF1VGA2Range;
static const DeviceGains m_baldeRF1Gains;
static const DeviceGains::GainRange m_funCubeProPlusRange;
static const DeviceGains m_funCubeProPlusGains;
static const DeviceGains::GainRange m_hackRFLNAGainRange;
static const DeviceGains::GainRange m_hackRFVGAGainRange;
static const DeviceGains m_hackRFGains;
static const DeviceGains::GainRange m_kiwiGainRange;
static const DeviceGains m_kiwiGains;
static const DeviceGains::GainRange m_limeRange;
static const DeviceGains m_limeGains;
static const DeviceGains::GainRange m_sdrplayV3LNAGainRange;
static const DeviceGains::GainRange m_sdrplayV3IFGainRange;
static const DeviceGains m_sdrplayV3Gains;
static const DeviceGains::GainRange m_plutoGainRange;
static const DeviceGains m_plutoGains;
static const DeviceGains::GainRange m_usrpGainRange;
static const DeviceGains m_usrpGains;
static const DeviceGains::GainRange m_xtrxGainRange;
static const DeviceGains m_xtrxGains;
static const QHash<RemoteTCPProtocol::Device, const DeviceGains *> m_gains;
void blockApplySettings(bool block);
void displaySettings();
QString gainText(int stage);
void displayGains();
void displayRemoteSettings();
void displayRemoteShift();
void sendSettings();
void updateSampleRateAndFrequency();
void applyPosition();
bool handleMessage(const Message& message);
void makeUIConnections();
private slots:
void handleInputMessages();
void on_startStop_toggled(bool checked);
void on_centerFrequency_changed(quint64 value);
void on_ppm_valueChanged(int value);
void on_dcOffset_toggled(bool checked);
void on_iqImbalance_toggled(bool checked);
void on_biasTee_toggled(bool checked);
void on_directSampling_toggled(bool checked);
void on_devSampleRate_changed(quint64 value);
void on_gain1_valueChanged(int value);
void on_gain2_valueChanged(int value);
void on_agc_toggled(bool checked);
void on_rfBW_changed(int value);
void on_sampleBits_currentIndexChanged(int index);
void on_dataPort_editingFinished();
void updateHardware();
void updateStatus();
void openDeviceSettingsDialog(const QPoint& p);
};
#endif // INCLUDE_ANDROIDSDRDRIVERINPUTGUI_H

View File

@ -0,0 +1,641 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AndroidSDRDriverInputGui</class>
<widget class="QWidget" name="AndroidSDRDriverInputGui">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>360</width>
<height>181</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>360</width>
<height>181</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>380</width>
<height>181</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>Remote TCP Input</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>2</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>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="deviceRateLayout">
<item>
<widget class="QLabel" name="deviceRateText">
<property name="toolTip">
<string>Device 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="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>
<pointsize>16</pointsize>
<bold>false</bold>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="toolTip">
<string>Center frequency in 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> kHz</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_ppm">
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="ppmLabel">
<property name="text">
<string>LO ppm</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="ppm">
<property name="toolTip">
<string>Local Oscillator ppm correction</string>
</property>
<property name="minimum">
<number>-200</number>
</property>
<property name="maximum">
<number>200</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="ppmText">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_rateTime">
<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>
<widget class="ButtonSwitch" name="biasTee">
<property name="toolTip">
<string>Enable bias tee</string>
</property>
<property name="text">
<string>T</string>
</property>
</widget>
</item>
<item>
<widget class="ButtonSwitch" name="directSampling">
<property name="toolTip">
<string>Direct sampling</string>
</property>
<property name="text">
<string>DS</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</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="sampleBitsLabel">
<property name="text">
<string>IQ</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="sampleBits">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>45</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Bit depth per I or Q sample transmitted over network</string>
</property>
<item>
<property name="text">
<string>8</string>
</property>
</item>
<item>
<property name="text">
<string>16</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLabel" name="sampleBitsUnits">
<property name="text">
<string>bits</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="dataAddressLabel">
<property name="minimumSize">
<size>
<width>10</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="dataPortSeparator">
<property name="text">
<string>:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="dataPort">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>60</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Remote data port (rtl_tcp defaults to 1234)</string>
</property>
<property name="inputMask">
<string>00000</string>
</property>
<property name="text">
<string>0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</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="sampleRateLayout">
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QLabel" name="devSampleRateLabel">
<property name="text">
<string>SR</string>
</property>
</widget>
</item>
<item>
<widget class="ValueDial" name="devSampleRate" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
<bold>false</bold>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="toolTip">
<string>Remote device sample rate</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="devSampleRateUnits">
<property name="text">
<string>S/s</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<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="rfBWLabel">
<property name="text">
<string>BW</string>
</property>
</widget>
</item>
<item>
<widget class="ValueDial" name="rfBW" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>32</width>
<height>16</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="toolTip">
<string>RF filter bandwidth (kHz)</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="rfBWUnits">
<property name="text">
<string>kHz</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="gainLayout">
<item>
<widget class="QLabel" name="gain1Label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="gain1">
<property name="toolTip">
<string>Gain</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gain1Text">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>40.0dB</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="gainLine1">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gain2Label">
<property name="text">
<string>Gain</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="gain2">
<property name="toolTip">
<string>Gain</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="gain2Text">
<property name="text">
<string>20dB</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_7">
<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="ButtonSwitch" name="agc">
<property name="toolTip">
<string>Toggle automatic gain control</string>
</property>
<property name="text">
<string>AGC</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_rfBW">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>ValueDial</class>
<extends>QWidget</extends>
<header>gui/valuedial.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>startStop</tabstop>
<tabstop>centerFrequency</tabstop>
<tabstop>ppm</tabstop>
<tabstop>dcOffset</tabstop>
<tabstop>iqImbalance</tabstop>
<tabstop>agc</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,149 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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"
#ifdef SERVER_MODE
#include "androidsdrdriverinput.h"
#else
#include "androidsdrdriverinputgui.h"
#endif
#include "androidsdrdriverinputplugin.h"
#include "androidsdrdriverinputwebapiadapter.h"
const PluginDescriptor AndroidSDRDriverInputPlugin::m_pluginDescriptor = {
QStringLiteral("AndroidSDRDriverInput"),
QStringLiteral("Android SDR Driver input"),
QStringLiteral("7.16.0"),
QStringLiteral("(c) Jon Beniston, M7RCE"),
QStringLiteral("https://github.com/f4exb/sdrangel"),
true,
QStringLiteral("https://github.com/f4exb/sdrangel")
};
static constexpr const char* const m_hardwareID = "AndroidSDRDriverInput";
static constexpr const char* const m_deviceTypeID = ANDROIDSDRDRIVERINPUT_DEVICE_TYPE_ID;
AndroidSDRDriverInputPlugin::AndroidSDRDriverInputPlugin(QObject* parent) :
QObject(parent)
{
}
const PluginDescriptor& AndroidSDRDriverInputPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void AndroidSDRDriverInputPlugin::initPlugin(PluginAPI* pluginAPI)
{
pluginAPI->registerSampleSource(m_deviceTypeID, this);
}
void AndroidSDRDriverInputPlugin::enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices)
{
if (listedHwIds.contains(m_hardwareID)) { // check if it was done
return;
}
originDevices.append(OriginDevice(
"Android SDR Driver",
m_hardwareID,
QString(),
0,
1, // nb Rx
0 // nb Tx
));
listedHwIds.append(m_hardwareID);
}
PluginInterface::SamplingDevices AndroidSDRDriverInputPlugin::enumSampleSources(const OriginDevices& originDevices)
{
SamplingDevices result;
for (OriginDevices::const_iterator it = originDevices.begin(); it != originDevices.end(); ++it)
{
if (it->hardwareId == m_hardwareID)
{
result.append(SamplingDevice(
it->displayableName,
m_hardwareID,
m_deviceTypeID,
it->serial,
it->sequence,
PluginInterface::SamplingDevice::BuiltInDevice,
PluginInterface::SamplingDevice::StreamSingleRx,
1,
0
));
}
}
return result;
}
#ifdef SERVER_MODE
DeviceGUI* AndroidSDRDriverInputPlugin::createSampleSourcePluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet)
{
(void) sourceId;
(void) widget;
(void) deviceUISet;
return 0;
}
#else
DeviceGUI* AndroidSDRDriverInputPlugin::createSampleSourcePluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet)
{
if(sourceId == m_deviceTypeID)
{
AndroidSDRDriverInputGui* gui = new AndroidSDRDriverInputGui(deviceUISet);
*widget = gui;
return gui;
}
else
{
return 0;
}
}
#endif
DeviceSampleSource *AndroidSDRDriverInputPlugin::createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI)
{
if (sourceId == m_deviceTypeID)
{
AndroidSDRDriverInput* input = new AndroidSDRDriverInput(deviceAPI);
return input;
}
else
{
return 0;
}
}
DeviceWebAPIAdapter *AndroidSDRDriverInputPlugin::createDeviceWebAPIAdapter() const
{
return new AndroidSDRDriverInputWebAPIAdapter();
}

View File

@ -0,0 +1,53 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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_ANDROIDSDRDRIVERINPUTPLUGIN_H
#define INCLUDE_ANDROIDSDRDRIVERINPUTPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
#define ANDROIDSDRDRIVERINPUT_DEVICE_TYPE_ID "sdrangel.samplesource.androidsdrdriverinput"
class PluginAPI;
class AndroidSDRDriverInputPlugin : public QObject, public PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID ANDROIDSDRDRIVERINPUT_DEVICE_TYPE_ID)
public:
explicit AndroidSDRDriverInputPlugin(QObject* parent = NULL);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
virtual void enumOriginDevices(QStringList& listedHwIds, OriginDevices& originDevices);
virtual SamplingDevices enumSampleSources(const OriginDevices& originDevices);
virtual DeviceGUI* createSampleSourcePluginInstanceGUI(
const QString& sourceId,
QWidget **widget,
DeviceUISet *deviceUISet);
virtual DeviceSampleSource* createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI);
virtual DeviceWebAPIAdapter* createDeviceWebAPIAdapter() const;
private:
static const PluginDescriptor m_pluginDescriptor;
};
#endif // INCLUDE_ANDROIDSDRDRIVERINPUTPLUGIN_H

View File

@ -0,0 +1,240 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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 "androidsdrdriverinputsettings.h"
AndroidSDRDriverInputSettings::AndroidSDRDriverInputSettings()
{
resetToDefaults();
}
void AndroidSDRDriverInputSettings::resetToDefaults()
{
m_centerFrequency = 435000000;
m_loPpmCorrection = 0;
m_dcBlock = false;
m_iqCorrection = false;
m_biasTee = false;
m_directSampling = false;
m_devSampleRate = 2000000;
for (int i = 0; i < m_maxGains; i++) {
m_gain[i] = 0;
}
m_agc = false;
m_rfBW = 2500000;
m_sampleBits = 8;
m_dataPort = 1234;
m_useReverseAPI = false;
m_reverseAPIAddress = "127.0.0.1";
m_reverseAPIPort = 8888;
m_reverseAPIDeviceIndex = 0;
}
QByteArray AndroidSDRDriverInputSettings::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_loPpmCorrection);
s.writeBool(2, m_dcBlock);
s.writeBool(3, m_iqCorrection);
s.writeBool(4, m_biasTee);
s.writeBool(5, m_directSampling);
s.writeS32(6, m_devSampleRate);
s.writeBool(9, m_agc);
s.writeS32(10, m_rfBW);
s.writeS32(15, m_sampleBits);
s.writeU32(16, m_dataPort);
s.writeBool(20, m_useReverseAPI);
s.writeString(21, m_reverseAPIAddress);
s.writeU32(22, m_reverseAPIPort);
s.writeU32(23, m_reverseAPIDeviceIndex);
for (int i = 0; i < m_maxGains; i++) {
s.writeS32(30+i, m_gain[i]);
}
return s.final();
}
bool AndroidSDRDriverInputSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
quint32 uintval;
d.readS32(1, &m_loPpmCorrection, 0);
d.readBool(2, &m_dcBlock, false);
d.readBool(3, &m_iqCorrection, false);
d.readBool(4, &m_biasTee, false);
d.readBool(5, &m_directSampling, false);
d.readS32(6, &m_devSampleRate, 2000000);
d.readBool(9, &m_agc, false);
d.readS32(10, &m_rfBW, 2500000);
d.readS32(15, &m_sampleBits, 8);
d.readU32(16, &uintval, 1234);
m_dataPort = uintval % (1<<16);
d.readBool(20, &m_useReverseAPI, false);
d.readString(21, &m_reverseAPIAddress, "127.0.0.1");
d.readU32(22, &uintval, 0);
if ((uintval > 1023) && (uintval < 65535)) {
m_reverseAPIPort = uintval;
} else {
m_reverseAPIPort = 8888;
}
d.readU32(23, &uintval, 0);
m_reverseAPIDeviceIndex = uintval > 99 ? 99 : uintval;
for (int i = 0; i < m_maxGains; i++) {
d.readS32(30+i, &m_gain[i], 0);
}
return true;
}
else
{
resetToDefaults();
return false;
}
}
void AndroidSDRDriverInputSettings::applySettings(const QStringList& settingsKeys, const AndroidSDRDriverInputSettings& settings)
{
if (settingsKeys.contains("centerFrequency")) {
m_centerFrequency = settings.m_centerFrequency;
}
if (settingsKeys.contains("loPpmCorrection")) {
m_loPpmCorrection = settings.m_loPpmCorrection;
}
if (settingsKeys.contains("dcBlock")) {
m_dcBlock = settings.m_dcBlock;
}
if (settingsKeys.contains("iqCorrection")) {
m_iqCorrection = settings.m_iqCorrection;
}
if (settingsKeys.contains("biasTee")) {
m_biasTee = settings.m_biasTee;
}
if (settingsKeys.contains("directSampling")) {
m_directSampling = settings.m_directSampling;
}
if (settingsKeys.contains("devSampleRate")) {
m_devSampleRate = settings.m_devSampleRate;
}
if (settingsKeys.contains("agc")) {
m_agc = settings.m_agc;
}
if (settingsKeys.contains("rfBW")) {
m_rfBW = settings.m_rfBW;
}
if (settingsKeys.contains("sampleBits")) {
m_sampleBits = settings.m_sampleBits;
}
if (settingsKeys.contains("dataPort")) {
m_dataPort = settings.m_dataPort;
}
if (settingsKeys.contains("_useReverseAPI")) {
m_useReverseAPI = settings.m_useReverseAPI;
}
if (settingsKeys.contains("reverseAPIAddress")) {
m_reverseAPIAddress = settings.m_reverseAPIAddress;
}
if (settingsKeys.contains("reverseAPIPort")) {
m_reverseAPIPort = settings.m_reverseAPIPort;
}
if (settingsKeys.contains("reverseAPIDeviceIndex")) {
m_reverseAPIDeviceIndex = settings.m_reverseAPIDeviceIndex;
}
for (int i = 0; i < m_maxGains; i++)
{
if (settingsKeys.contains(QString("gain[%1]").arg(i))) {
m_gain[i] = settings.m_gain[i];
}
}
}
QString AndroidSDRDriverInputSettings::getDebugString(const QStringList& settingsKeys, bool force) const
{
std::ostringstream ostr;
if (settingsKeys.contains("centerFrequency") || force) {
ostr << " m_centerFrequency: " << m_centerFrequency;
}
if (settingsKeys.contains("loPpmCorrection") || force) {
ostr << " m_loPpmCorrection: " << m_loPpmCorrection;
}
if (settingsKeys.contains("dcBlock") || force) {
ostr << " m_dcBlock: " << m_dcBlock;
}
if (settingsKeys.contains("iqCorrection") || force) {
ostr << " m_iqCorrection: " << m_iqCorrection;
}
if (settingsKeys.contains("biasTee") || force) {
ostr << " m_biasTee: " << m_biasTee;
}
if (settingsKeys.contains("directSampling") || force) {
ostr << " m_directSampling: " << m_directSampling;
}
if (settingsKeys.contains("devSampleRate") || force) {
ostr << " m_devSampleRate: " << m_devSampleRate;
}
if (settingsKeys.contains("agc") || force) {
ostr << " m_agc: " << m_agc;
}
if (settingsKeys.contains("rfBW") || force) {
ostr << " m_rfBW: " << m_rfBW;
}
if (settingsKeys.contains("sampleBits") || force) {
ostr << " m_sampleBits: " << m_sampleBits;
}
if (settingsKeys.contains("dataPort") || force) {
ostr << " m_dataPort: " << m_dataPort;
}
if (settingsKeys.contains("useReverseAPI") || force) {
ostr << " m_useReverseAPI: " << m_useReverseAPI;
}
if (settingsKeys.contains("reverseAPIAddress") || force) {
ostr << " m_reverseAPIAddress: " << m_reverseAPIAddress.toStdString();
}
if (settingsKeys.contains("reverseAPIPort") || force) {
ostr << " m_reverseAPIPort: " << m_reverseAPIPort;
}
if (settingsKeys.contains("reverseAPIDeviceIndex") || force) {
ostr << " m_reverseAPIDeviceIndex: " << m_reverseAPIDeviceIndex;
}
for (int i = 0; i < m_maxGains; i++)
{
if (settingsKeys.contains(QString("gain[%1]").arg(i))) {
ostr << QString(" gain[%1]: ").arg(i).toStdString() << m_gain[i];
}
}
return QString(ostr.str().c_str());
}

View File

@ -0,0 +1,54 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2017 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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_ANDROIDSDRDRIVERINPUT_ANDROIDSDRDRIVERINPUTSETTINGS_H_
#define PLUGINS_SAMPLESOURCE_ANDROIDSDRDRIVERINPUT_ANDROIDSDRDRIVERINPUTSETTINGS_H_
#include <QByteArray>
#include <QString>
struct AndroidSDRDriverInputSettings
{
static const int m_maxGains = 2;
uint64_t m_centerFrequency;
qint32 m_loPpmCorrection;
bool m_dcBlock;
bool m_iqCorrection;
bool m_biasTee;
bool m_directSampling; // RTLSDR only
int m_devSampleRate;
qint32 m_gain[m_maxGains]; // 10ths of a dB
bool m_agc;
qint32 m_rfBW;
qint32 m_sampleBits; // Number of bits used to transmit IQ samples (8,16)
quint16 m_dataPort;
bool m_useReverseAPI;
QString m_reverseAPIAddress;
uint16_t m_reverseAPIPort;
uint16_t m_reverseAPIDeviceIndex;
AndroidSDRDriverInputSettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void applySettings(const QStringList& settingsKeys, const AndroidSDRDriverInputSettings& settings);
QString getDebugString(const QStringList& settingsKeys, bool force=false) const;
};
#endif /* PLUGINS_SAMPLESOURCE_ANDROIDSDRDRIVERINPUT_ANDROIDSDRDRIVERINPUTSETTINGS_H_ */

View File

@ -0,0 +1,763 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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 <QUdpSocket>
#include <QDebug>
#include "dsp/dspcommands.h"
#include "dsp/dspengine.h"
#include "device/deviceapi.h"
#include "androidsdrdriverinputtcphandler.h"
#include "androidsdrdriverinput.h"
#include "../../channelrx/remotetcpsink/remotetcpprotocol.h"
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInputTCPHandler::MsgReportRemoteDevice, Message)
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInputTCPHandler::MsgReportConnection, Message)
MESSAGE_CLASS_DEFINITION(AndroidSDRDriverInputTCPHandler::MsgConfigureTcpHandler, Message)
AndroidSDRDriverInputTCPHandler::AndroidSDRDriverInputTCPHandler(SampleSinkFifo *sampleFifo, DeviceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_running(false),
m_dataSocket(nullptr),
m_tcpBuf(nullptr),
m_sampleFifo(sampleFifo),
m_messageQueueToGUI(0),
m_fillBuffer(true),
m_reconnectTimer(this),
m_rsp0(false),
m_converterBuffer(nullptr),
m_converterBufferNbSamples(0),
m_settings()
{
m_tcpBuf = new char[m_sampleFifo->size()*2*4];
connect(&m_reconnectTimer, SIGNAL(timeout()), this, SLOT(reconnect()));
m_reconnectTimer.setSingleShot(true);
}
AndroidSDRDriverInputTCPHandler::~AndroidSDRDriverInputTCPHandler()
{
delete[] m_tcpBuf;
if (m_converterBuffer) {
delete[] m_converterBuffer;
}
cleanup();
}
void AndroidSDRDriverInputTCPHandler::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_inputMessageQueue.clear();
}
void AndroidSDRDriverInputTCPHandler::start()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug("AndroidSDRDriverInputTCPHandler::start");
if (m_running) {
return;
}
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
connect(thread(), SIGNAL(started()), this, SLOT(started()));
connect(thread(), SIGNAL(finished()), this, SLOT(finished()));
m_running = true;
}
void AndroidSDRDriverInputTCPHandler::stop()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug("AndroidSDRDriverInputTCPHandler::stop");
disconnect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
}
void AndroidSDRDriverInputTCPHandler::started()
{
QMutexLocker mutexLocker(&m_mutex);
disconnect(thread(), SIGNAL(started()), this, SLOT(started()));
}
void AndroidSDRDriverInputTCPHandler::finished()
{
QMutexLocker mutexLocker(&m_mutex);
disconnectFromHost();
disconnect(thread(), SIGNAL(finished()), this, SLOT(finished()));
m_running = false;
}
void AndroidSDRDriverInputTCPHandler::connectToHost(const QString& address, quint16 port)
{
qDebug("AndroidSDRDriverInputTCPHandler::connectToHost: connect to %s:%d", address.toStdString().c_str(), port);
m_dataSocket = new QTcpSocket(this);
m_fillBuffer = true;
m_readMetaData = false;
connect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()));
connect(m_dataSocket, SIGNAL(connected()), this, SLOT(connected()));
connect(m_dataSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(m_dataSocket, &QAbstractSocket::errorOccurred, this, &AndroidSDRDriverInputTCPHandler::errorOccurred);
m_dataSocket->connectToHost(address, port);
}
void AndroidSDRDriverInputTCPHandler::disconnectFromHost()
{
if (m_dataSocket)
{
qDebug() << "AndroidSDRDriverInputTCPHandler::disconnectFromHost";
disconnect(m_dataSocket, SIGNAL(readyRead()), this, SLOT(dataReadyRead()));
disconnect(m_dataSocket, SIGNAL(connected()), this, SLOT(connected()));
disconnect(m_dataSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
disconnect(m_dataSocket, &QAbstractSocket::errorOccurred, this, &AndroidSDRDriverInputTCPHandler::errorOccurred);
m_dataSocket->disconnectFromHost();
cleanup();
}
}
void AndroidSDRDriverInputTCPHandler::cleanup()
{
if (m_dataSocket)
{
m_dataSocket->deleteLater();
m_dataSocket = nullptr;
}
}
// Clear input buffer when settings change that invalidate the data in it
// E.g. sample rate or bit depth
void AndroidSDRDriverInputTCPHandler::clearBuffer()
{
if (m_dataSocket)
{
m_dataSocket->flush();
m_dataSocket->readAll();
m_fillBuffer = true;
}
}
void AndroidSDRDriverInputTCPHandler::setSampleRate(int sampleRate)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setSampleRate;
RemoteTCPProtocol::encodeUInt32(&request[1], sampleRate);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setCenterFrequency(quint64 frequency)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setCenterFrequency;
RemoteTCPProtocol::encodeUInt32(&request[1], frequency);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setTunerAGC(bool agc)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerGainMode;
RemoteTCPProtocol::encodeUInt32(&request[1], agc);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setTunerGain(int gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerGain;
RemoteTCPProtocol::encodeUInt32(&request[1], gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setFreqCorrection(int correction)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setFrequencyCorrection;
RemoteTCPProtocol::encodeUInt32(&request[1], correction);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setIFGain(quint16 stage, quint16 gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerIFGain;
RemoteTCPProtocol::encodeUInt32(&request[1], (stage << 16) | gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setAGC(bool agc)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setAGCMode;
RemoteTCPProtocol::encodeUInt32(&request[1], agc);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setDirectSampling(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setDirectSampling;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setDCOffsetRemoval(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setDCOffsetRemoval;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setIQCorrection(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setIQCorrection;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setBiasTee(bool enabled)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setBiasTee;
RemoteTCPProtocol::encodeUInt32(&request[1], enabled);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setBandwidth(int bandwidth)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setTunerBandwidth;
RemoteTCPProtocol::encodeUInt32(&request[1], bandwidth);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setDecimation(int dec)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setDecimation;
RemoteTCPProtocol::encodeUInt32(&request[1], dec);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setChannelSampleRate(int sampleRate)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setChannelSampleRate;
RemoteTCPProtocol::encodeUInt32(&request[1], sampleRate);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setSampleBitDepth(int sampleBits)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::setSampleBitDepth;
RemoteTCPProtocol::encodeUInt32(&request[1], sampleBits);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setAndroidGainByPercentage(int gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::androidGainByPercentage;
RemoteTCPProtocol::encodeUInt32(&request[1], gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::setAndroidEnable16BitSigned(bool enable)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::androidEnable16BitSigned;
RemoteTCPProtocol::encodeUInt32(&request[1], enable);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::rspSetAGC(bool agc)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::rspSetAGC;
RemoteTCPProtocol::encodeUInt32(&request[1], agc);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::rspSetIfGainR(int gain)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::rspSetIfGainR;
RemoteTCPProtocol::encodeUInt32(&request[1], gain);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::rspSetLNAState(int state)
{
QMutexLocker mutexLocker(&m_mutex);
quint8 request[5];
request[0] = RemoteTCPProtocol::rspSetLNAState;
RemoteTCPProtocol::encodeUInt32(&request[1], state);
if (m_dataSocket) {
m_dataSocket->write((char*)request, sizeof(request));
}
}
void AndroidSDRDriverInputTCPHandler::applySettings(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force)
{
qDebug() << "AndroidSDRDriverInputTCPHandler::applySettings: "
<< "force: " << force
<< settings.getDebugString(settingsKeys, force);
QMutexLocker mutexLocker(&m_mutex);
if (settingsKeys.contains("centerFrequency") || force) {
setCenterFrequency(settings.m_centerFrequency);
}
if (settingsKeys.contains("loPpmCorrection") || force) {
setFreqCorrection(settings.m_loPpmCorrection);
}
if (settingsKeys.contains("dcBlock") || force) {
setDCOffsetRemoval(settings.m_dcBlock);
}
if (settingsKeys.contains("iqCorrection") || force) {
setIQCorrection(settings.m_iqCorrection);
}
if (settingsKeys.contains("biasTee") || force) {
setBiasTee(settings.m_biasTee);
}
if (settingsKeys.contains("directSampling") || force) {
setDirectSampling(settings.m_directSampling);
}
if (settingsKeys.contains("devSampleRate") || force) {
setSampleRate(settings.m_devSampleRate);
}
if (settingsKeys.contains("agc") || force)
{
if (m_rsp0) {
rspSetAGC(settings.m_agc);
} else {
setAGC(settings.m_agc);
}
}
if (force)
{
if (!m_rsp0) {
setTunerAGC(1); // The SDRangel RTLSDR driver always has tuner gain as manual
}
}
if (settingsKeys.contains("gain[0]") || force)
{
if (m_rsp0) {
rspSetLNAState(settings.m_gain[0] / 10);
} else {
setTunerGain(settings.m_gain[0]);
}
}
for (int i = 1; i < 2; i++)
{
if (settingsKeys.contains(QString("gain[%1]").arg(i)) || force)
{
if (m_rsp0 && (i == 1)) {
rspSetIfGainR(settings.m_gain[i] / -10);
} else {
setIFGain(i, settings.m_gain[i]);
}
}
}
if (settingsKeys.contains("rfBW") || force) {
setBandwidth(settings.m_rfBW);
}
if (settingsKeys.contains("sampleBits") || force)
{
if (m_rsp0) {
setAndroidEnable16BitSigned(settings.m_sampleBits == 16);
} else {
setSampleBitDepth(settings.m_sampleBits);
}
clearBuffer();
}
// Don't use force, as disconnect can cause rtl_tcp to quit
if (settingsKeys.contains("dataPort") || (m_dataSocket == nullptr))
{
disconnectFromHost();
connectToHost("127.0.0.1", settings.m_dataPort);
}
if (force) {
m_settings = settings;
} else {
m_settings.applySettings(settingsKeys, settings);
}
}
void AndroidSDRDriverInputTCPHandler::connected()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug() << "AndroidSDRDriverInputTCPHandler::connected";
// Force settings to be sent to remote device
applySettings(m_settings, QList<QString>(), true);
if (m_messageQueueToGUI)
{
MsgReportConnection *msg = MsgReportConnection::create(true);
m_messageQueueToGUI->push(msg);
}
}
void AndroidSDRDriverInputTCPHandler::reconnect()
{
QMutexLocker mutexLocker(&m_mutex);
if (!m_dataSocket) {
connectToHost("127.0.0.1", m_settings.m_dataPort);
}
}
void AndroidSDRDriverInputTCPHandler::disconnected()
{
QMutexLocker mutexLocker(&m_mutex);
qDebug() << "AndroidSDRDriverInputTCPHandler::disconnected";
cleanup();
if (m_messageQueueToGUI)
{
MsgReportConnection *msg = MsgReportConnection::create(false);
m_messageQueueToGUI->push(msg);
}
// Try to reconnect
m_reconnectTimer.start(500);
}
void AndroidSDRDriverInputTCPHandler::errorOccurred(QAbstractSocket::SocketError socketError)
{
qDebug() << "AndroidSDRDriverInputTCPHandler::errorOccurred: " << socketError;
cleanup();
if (m_messageQueueToGUI)
{
MsgReportConnection *msg = MsgReportConnection::create(false);
m_messageQueueToGUI->push(msg);
}
// Try to reconnect
m_reconnectTimer.start(500);
}
void AndroidSDRDriverInputTCPHandler::dataReadyRead()
{
QMutexLocker mutexLocker(&m_mutex);
if (!m_readMetaData)
{
quint8 metaData[RemoteTCPProtocol::m_rtl0MetaDataSize];
if (m_dataSocket->bytesAvailable() >= (qint64)sizeof(metaData))
{
qint64 bytesRead = m_dataSocket->read((char *)&metaData[0], 4);
if (bytesRead == 4)
{
// Read first 4 bytes which indicate which protocol is in use.
char protochars[5];
memcpy(protochars, metaData, 4);
protochars[4] = '\0';
QString protocol(protochars);
qDebug() << "RemoteTCPInputTCPHandler::dataReadyRead: Protocol: " << QByteArray((char *)metaData, 4).toHex() << " - " << protocol;
if (protocol == "RTL0")
{
m_rsp0 = false;
bytesRead = m_dataSocket->read((char *)&metaData[4], RemoteTCPProtocol::m_rtl0MetaDataSize-4);
RemoteTCPProtocol::Device tuner = (RemoteTCPProtocol::Device)RemoteTCPProtocol::extractUInt32(&metaData[4]);
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(MsgReportRemoteDevice::create(tuner, protocol));
}
// Set default gain to something reasonable
if (m_settings.m_gain[0] == 0)
{
AndroidSDRDriverInputSettings& settings = m_settings;
if (tuner == RemoteTCPProtocol::RTLSDR_E4000) {
settings.m_gain[0] = 290.0;
} else {
settings.m_gain[0] = 297.0;
}
QList<QString> settingsKeys{"gain[0]"};
if (m_messageQueueToInput) {
m_messageQueueToInput->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
}
}
else if (protocol == "MIR0")
{
// Android RTLplay driver uses MIR0 protocol, but tuner type is 0 so no way of knowing what device is used
m_rsp0 = true;
bytesRead = m_dataSocket->read((char *)&metaData[4], RemoteTCPProtocol::m_rtl0MetaDataSize-4);
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(MsgReportRemoteDevice::create(RemoteTCPProtocol::SDRPLAY_V3_RSPDUO, protocol));
}
// Switch to 16-bit
// If we don't do this straight away, it doesn't seem reliable
setAndroidEnable16BitSigned(true);
if (m_settings.m_sampleBits != 16)
{
AndroidSDRDriverInputSettings& settings = m_settings;
settings.m_sampleBits = 16;
QList<QString> settingsKeys{"sampleBits"};
if (m_messageQueueToInput) {
m_messageQueueToInput->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
}
// Set default gains to something reasonable
if ((m_settings.m_gain[0] == 0) && (m_settings.m_gain[1] == 0))
{
AndroidSDRDriverInputSettings& settings = m_settings;
settings.m_gain[0] = 40;
settings.m_gain[1] = -400;
QList<QString> settingsKeys{"gain[0]", "gain[1]"};
if (m_messageQueueToInput) {
m_messageQueueToInput->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
if (m_messageQueueToGUI) {
m_messageQueueToGUI->push(AndroidSDRDriverInput::MsgConfigureAndroidSDRDriverInput::create(settings, settingsKeys));
}
}
}
else
{
qDebug() << "AndroidSDRDriverInputTCPHandler::dataReadyRead: Unknown protocol: " << QByteArray((char *)metaData, 4).toHex() << " - " << protocol;
}
}
else
{
qDebug() << "AndroidSDRDriverInputTCPHandler::dataReadyRead: Failed to read protocol ID";
}
m_readMetaData = true;
}
else
{
qDebug() << "AndroidSDRDriverInputTCPHandler::dataReadyRead: Not enough metadata";
}
}
else
{
int bytesPerSample = m_settings.m_sampleBits / 8;
unsigned int remaining = m_sampleFifo->size() - m_sampleFifo->fill();
int requiredSamples = (int)std::min((unsigned int)(m_dataSocket->bytesAvailable()/(2*bytesPerSample)), remaining);
if (requiredSamples >= 0)
{
m_dataSocket->read(&m_tcpBuf[0], requiredSamples*2*bytesPerSample);
convert(requiredSamples);
}
}
}
// The following code assumes host is little endian
void AndroidSDRDriverInputTCPHandler::convert(int nbSamples)
{
if (nbSamples > (int) m_converterBufferNbSamples)
{
if (m_converterBuffer) {
delete[] m_converterBuffer;
}
m_converterBuffer = new int32_t[nbSamples*2];
}
if ((m_settings.m_sampleBits == 32) && (SDR_RX_SAMP_SZ == 24))
{
m_sampleFifo->write(reinterpret_cast<quint8*>(m_tcpBuf), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 16))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint16 *out = (qint16 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (((qint16)in[is]) - 128) << 8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 24))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint32 *out = (qint32 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (((qint32)in[is]) - 128) << 16;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 24))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint32 *out = (qint32 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (((in[3*is+2] << 16) | (in[3*is+1] << 8) | in[3*is]) << 8) >> 8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 16))
{
quint8 *in = (quint8 *)m_tcpBuf;
qint16 *out = (qint16 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = (in[3*is+2] << 8) | in[3*is+1];
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24))
{
qint16 *in = (qint16 *)m_tcpBuf;
qint32 *out = (qint32 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
if (m_rsp0) {
out[is] = in[is] << 12;
} else {
out[is] = in[is] << 8;
}
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else if ((m_settings.m_sampleBits == 32) && (SDR_RX_SAMP_SZ == 16))
{
qint32 *in = (qint32 *)m_tcpBuf;
qint16 *out = (qint16 *)m_converterBuffer;
for (int is = 0; is < nbSamples*2; is++) {
out[is] = in[is] >> 8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(out), nbSamples*sizeof(Sample));
}
else // invalid size
{
qWarning("AndroidSDRDriverInputTCPHandler::convert: unexpected sample size in stream: %d bits", (int) m_settings.m_sampleBits);
}
}
void AndroidSDRDriverInputTCPHandler::handleInputMessages()
{
Message* message;
while ((message = m_inputMessageQueue.pop()) != 0)
{
if (handleMessage(*message)) {
delete message;
}
}
}
bool AndroidSDRDriverInputTCPHandler::handleMessage(const Message& cmd)
{
if (MsgConfigureTcpHandler::match(cmd))
{
qDebug() << "AndroidSDRDriverInputTCPHandler::handleMessage: MsgConfigureTcpHandler";
MsgConfigureTcpHandler& notif = (MsgConfigureTcpHandler&) cmd;
applySettings(notif.getSettings(), notif.getSettingsKeys(), notif.getForce());
return true;
}
else
{
return false;
}
}

View File

@ -0,0 +1,185 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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_ANDROIDSDRDRIVERINPUT_ANDROIDSDRDRIVERINPUTUDPHANDLER_H_
#define PLUGINS_SAMPLESOURCE_ANDROIDSDRDRIVERINPUT_ANDROIDSDRDRIVERINPUTUDPHANDLER_H_
#include <QObject>
#include <QTcpSocket>
#include <QHostAddress>
#include <QRecursiveMutex>
#include <QDateTime>
#include "util/messagequeue.h"
#include "androidsdrdriverinputsettings.h"
#include "../../channelrx/remotetcpsink/remotetcpprotocol.h"
class SampleSinkFifo;
class MessageQueue;
class DeviceAPI;
class AndroidSDRDriverInputTCPHandler : public QObject
{
Q_OBJECT
public:
class MsgConfigureTcpHandler : public Message {
MESSAGE_CLASS_DECLARATION
public:
const AndroidSDRDriverInputSettings& getSettings() const { return m_settings; }
const QList<QString>& getSettingsKeys() const { return m_settingsKeys; }
bool getForce() const { return m_force; }
static MsgConfigureTcpHandler* create(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force)
{
return new MsgConfigureTcpHandler(settings, settingsKeys, force);
}
private:
AndroidSDRDriverInputSettings m_settings;
QList<QString> m_settingsKeys;
bool m_force;
MsgConfigureTcpHandler(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force) :
Message(),
m_settings(settings),
m_settingsKeys(settingsKeys),
m_force(force)
{ }
};
class MsgReportRemoteDevice : public Message {
MESSAGE_CLASS_DECLARATION
public:
RemoteTCPProtocol::Device getDevice() const { return m_device; }
QString getProtocol() const { return m_protocol; }
static MsgReportRemoteDevice* create(RemoteTCPProtocol::Device device, const QString& protocol)
{
return new MsgReportRemoteDevice(device, protocol);
}
protected:
RemoteTCPProtocol::Device m_device;
QString m_protocol;
MsgReportRemoteDevice(RemoteTCPProtocol::Device device, const QString& protocol) :
Message(),
m_device(device),
m_protocol(protocol)
{ }
};
class MsgReportConnection : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getConnected() const { return m_connected; }
static MsgReportConnection* create(bool connected)
{
return new MsgReportConnection(connected);
}
protected:
bool m_connected;
MsgReportConnection(bool connected) :
Message(),
m_connected(connected)
{ }
};
AndroidSDRDriverInputTCPHandler(SampleSinkFifo* sampleFifo, DeviceAPI *deviceAPI);
~AndroidSDRDriverInputTCPHandler();
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
void setMessageQueueToInput(MessageQueue *queue) { m_messageQueueToInput = queue; }
void setMessageQueueToGUI(MessageQueue *queue) { m_messageQueueToGUI = queue; }
void reset();
void start();
void stop();
int getBufferGauge() const { return 0; }
public slots:
void dataReadyRead();
void connected();
void disconnected();
void errorOccurred(QAbstractSocket::SocketError socketError);
private:
DeviceAPI *m_deviceAPI;
bool m_running;
QTcpSocket *m_dataSocket;
char *m_tcpBuf;
SampleSinkFifo *m_sampleFifo;
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
MessageQueue *m_messageQueueToInput;
MessageQueue *m_messageQueueToGUI;
bool m_readMetaData;
bool m_fillBuffer;
QTimer m_reconnectTimer;
QDateTime m_prevDateTime;
bool m_rsp0;
int32_t *m_converterBuffer;
uint32_t m_converterBufferNbSamples;
QRecursiveMutex m_mutex;
AndroidSDRDriverInputSettings m_settings;
void applyTCPLink(const QString& address, quint16 port);
bool handleMessage(const Message& message);
void convert(int nbSamples);
void connectToHost(const QString& address, quint16 port);
void disconnectFromHost();
void cleanup();
void clearBuffer();
void setSampleRate(int sampleRate);
void setCenterFrequency(quint64 frequency);
void setTunerAGC(bool agc);
void setTunerGain(int gain);
void setFreqCorrection(int correction);
void setIFGain(quint16 stage, quint16 gain);
void setAGC(bool agc);
void setDirectSampling(bool enabled);
void setDCOffsetRemoval(bool enabled);
void setIQCorrection(bool enabled);
void setBiasTee(bool enabled);
void setBandwidth(int bandwidth);
void setDecimation(int dec);
void setChannelSampleRate(int dec);
void setChannelFreqOffset(int offset);
void setChannelGain(int gain);
void setSampleBitDepth(int sampleBits);
void setAndroidGainByPercentage(int gain);
void setAndroidEnable16BitSigned(bool enable);
void rspSetAGC(bool agc);
void rspSetIfGainR(int gain);
void rspSetLNAState(int state);
void applySettings(const AndroidSDRDriverInputSettings& settings, const QList<QString>& settingsKeys, bool force = false);
private slots:
void started();
void finished();
void handleInputMessages();
void reconnect();
};
#endif /* PLUGINS_SAMPLESOURCE_ANDROIDSDRDRIVERINPUT_ANDROIDSDRDRIVERINPUTUDPHANDLER_H_ */

View File

@ -0,0 +1,50 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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 "SWGDeviceSettings.h"
#include "androidsdrdriverinput.h"
#include "androidsdrdriverinputwebapiadapter.h"
AndroidSDRDriverInputWebAPIAdapter::AndroidSDRDriverInputWebAPIAdapter()
{}
AndroidSDRDriverInputWebAPIAdapter::~AndroidSDRDriverInputWebAPIAdapter()
{}
int AndroidSDRDriverInputWebAPIAdapter::webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage)
{
(void) errorMessage;
response.setAndroidSdrDriverInputSettings(new SWGSDRangel::SWGAndroidSDRDriverInputSettings());
response.getAndroidSdrDriverInputSettings()->init();
AndroidSDRDriverInput::webapiFormatDeviceSettings(response, m_settings);
return 200;
}
int AndroidSDRDriverInputWebAPIAdapter::webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage)
{
(void) force; // no action
(void) errorMessage;
AndroidSDRDriverInput::webapiUpdateDeviceSettings(m_settings, deviceSettingsKeys, response);
return 200;
}

View File

@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019 Edouard Griffiths, F4EXB //
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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 "device/devicewebapiadapter.h"
#include "androidsdrdriverinputsettings.h"
class AndroidSDRDriverInputWebAPIAdapter : public DeviceWebAPIAdapter
{
public:
AndroidSDRDriverInputWebAPIAdapter();
virtual ~AndroidSDRDriverInputWebAPIAdapter();
virtual QByteArray serialize() { return m_settings.serialize(); }
virtual bool deserialize(const QByteArray& data) { return m_settings.deserialize(data); }
virtual int webapiSettingsGet(
SWGSDRangel::SWGDeviceSettings& response,
QString& errorMessage);
virtual int webapiSettingsPutPatch(
bool force,
const QStringList& deviceSettingsKeys,
SWGSDRangel::SWGDeviceSettings& response, // query + response
QString& errorMessage);
private:
AndroidSDRDriverInputSettings m_settings;
};

View File

@ -0,0 +1,70 @@
<h1>Android SDR Driver Input Olugin</h1>
<h2>Introduction</h2>
This input sample source plugin gets its I/Q samples from the Android [SDR Driver](https://play.google.com/store/apps/details?id=marto.rtl_tcp_andro&hl=en&gl=US) or [SDRplay Driver](https://play.google.com/store/apps/details?id=com.sdrplay.driver&hl=en&gl=US) apps.
These apps enable support for RTL SDR, HackRF and SDRPlay SDRs.
<h2>Interface</h2>
![Android SDR Driver input plugin GUI](../../../doc/img/AndroidSDRDriverInput_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
- Red square icon: an error has occured with the connection to the device. The plugin will continually try to reconnect.
<h3>2: Center frequency</h3>
This is the center frequency in kHz of the device.
<h3>3: Stream sample rate</h3>
Network I/Q sample rate in kS/s.
<h3>4: Local oscillator correction</h3>
This is the correction to be applied to the device's local oscillator in ppm.
<h3>5: DC offset correction</h3>
Check this button to enable DC offset correction on the device.
<h3>6: IQ imbalance correction</h3>
Check this button to enable IQ imbalance correction on the device.
<h3>7: Bias tee</h3>
Check this button to enable a bias tee, if the device supports it.
<h3>8: Direct sampling mode</h3>
Use this button to activate RTL-SDR's direct sampling mode. This can be used to tune to HF frequencies.
<h3>9: Sample bit depth</h3>
Specifies number of bits per I/Q sample transmitted via TCP/IP. This should be 8 for RTL SDR, but can be 16 for SDRPlay.
<h3>10: Server TCP Port</h3>
TCP port of SDR Driver to connect to. Typically 1234.
<h3>11: Sample rate</h3>
Specify the device's sample rate in samples per second (S/s).
<h3>12: RF Bandwidth</h3>
Specifies the bandwidth in kHz of the analog filter in the device. Available bandwidths are dependent upon the device.
<h3>13: Gain</h3>
Specify gain in dB applied in various stages of the device. Available gains will depend upon the type of device.
<h3>12: AGC</h3>
Check to enable automatic gain control in the device. How AGC works is device dependent.

View File

@ -4870,6 +4870,11 @@ bool WebAPIRequestMapper::getDeviceSettings(
deviceSettings->setAirspyHfSettings(new SWGSDRangel::SWGAirspyHFSettings());
deviceSettings->getAirspyHfSettings()->fromJsonObject(settingsJsonObject);
}
else if (deviceSettingsKey == "androidSDRDriverInputSettings")
{
deviceSettings->setAndroidSdrDriverInputSettings(new SWGSDRangel::SWGAndroidSDRDriverInputSettings());
deviceSettings->getAndroidSdrDriverInputSettings()->fromJsonObject(settingsJsonObject);
}
else if (deviceSettingsKey == "audioCATSISOSettings")
{
deviceSettings->setAudioCatsisoSettings(new SWGSDRangel::SWGAudioCATSISOSettings());
@ -5367,6 +5372,7 @@ void WebAPIRequestMapper::resetDeviceSettings(SWGSDRangel::SWGDeviceSettings& de
deviceSettings.setDeviceHwType(nullptr);
deviceSettings.setAirspySettings(nullptr);
deviceSettings.setAirspyHfSettings(nullptr);
deviceSettings.setAndroidSdrDriverInputSettings(nullptr);
deviceSettings.setAudioInputSettings(nullptr);
deviceSettings.setBladeRf1InputSettings(nullptr);
deviceSettings.setBladeRf1OutputSettings(nullptr);
@ -5398,6 +5404,7 @@ void WebAPIRequestMapper::resetDeviceReport(SWGSDRangel::SWGDeviceReport& device
deviceReport.setDeviceHwType(nullptr);
deviceReport.setAirspyHfReport(nullptr);
deviceReport.setAirspyReport(nullptr);
deviceReport.setAndroidSdrDriverInputReport(nullptr);
deviceReport.setFileInputReport(nullptr);
deviceReport.setLimeSdrInputReport(nullptr);
deviceReport.setLimeSdrOutputReport(nullptr);

View File

@ -96,6 +96,7 @@ const QMap<QString, QString> WebAPIUtils::m_deviceIdToSettingsKey = {
{"sdrangel.samplesink.aaroniartsaoutput", "aaroniaRTSAOutputSettings"},
{"sdrangel.samplesource.airspy", "airspySettings"},
{"sdrangel.samplesource.airspyhf", "airspyHFSettings"},
{"sdrangel.samplesource.androidsdrdriverinput", "androidSDRDriverInputSettings"},
{"sdrangel.samplemimo.audiocatsiso", "audioCATSISOSettings"},
{"sdrangel.samplesource.audioinput", "audioInputSettings"},
{"sdrangel.samplesink.audiooutput", "audioOutputSettings"},
@ -221,6 +222,7 @@ const QMap<QString, QString> WebAPIUtils::m_sourceDeviceHwIdToSettingsKey = {
{"AaroniaRTSA", "aaroniaRTSASettings"},
{"Airspy", "airspySettings"},
{"AirspyHF", "airspyHFSettings"},
{"AndroidSDRDriverInput", "androidSDRDriverInputSettings"},
{"AudioInput", "audioInputSettings"},
{"BladeRF1", "bladeRF1InputSettings"},
{"BladeRF2", "bladeRF2InputSettings"},

View File

@ -0,0 +1,45 @@
AndroidSDRDriverInputSettings:
description: AndroidSDRDriverInput
properties:
centerFrequency:
type: integer
format: int64
loPpmCorrection:
type: integer
dcBlock:
type: integer
iqCorrection:
type: integer
biasTee:
type: integer
directSampling:
type: integer
devSampleRate:
type: integer
log2Decim:
type: integer
gain:
type: integer
agc:
type: integer
rfBW:
type: integer
sampleBits:
type: integer
dataPort:
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
AndroidSDRDriverInputReport:
description: AndroidSDRDriverInput
properties:
sampleRate:
type: integer

View File

@ -15,6 +15,8 @@ DeviceReport:
$ref: "http://swgserver:8081/api/swagger/include/Airspy.yaml#/AirspyReport"
airspyHFReport:
$ref: "http://swgserver:8081/api/swagger/include/AirspyHF.yaml#/AirspyHFReport"
androidSDRDriverInputReport:
$ref: "http://swgserver:8081/api/swagger/include/AndroidSDRDriverInput.yaml#/AndroidSDRDriverInputReport"
bladeRF2InputReport:
$ref: "http://swgserver:8081/api/swagger/include/BladeRF2.yaml#/BladeRF2InputReport"
bladeRF2OutputReport:

View File

@ -18,6 +18,8 @@ DeviceSettings:
$ref: "http://swgserver:8081/api/swagger/include/Airspy.yaml#/AirspySettings"
airspyHFSettings:
$ref: "http://swgserver:8081/api/swagger/include/AirspyHF.yaml#/AirspyHFSettings"
androidSDRDriverInputSettings:
$ref: "http://swgserver:8081/api/swagger/include/AndroidSDRDriverInput.yaml#/AndroidSDRDriverInputSettings"
audioCATSISOSettings:
$ref: "http://swgserver:8081/api/swagger/include/AudioCATSISO.yaml#/AudioCATSISOSettings"
audioInputSettings:

View File

@ -0,0 +1,108 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 7.0.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
#include "SWGAndroidSDRDriverInputReport.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGAndroidSDRDriverInputReport::SWGAndroidSDRDriverInputReport(QString* json) {
init();
this->fromJson(*json);
}
SWGAndroidSDRDriverInputReport::SWGAndroidSDRDriverInputReport() {
sample_rate = 0;
m_sample_rate_isSet = false;
}
SWGAndroidSDRDriverInputReport::~SWGAndroidSDRDriverInputReport() {
this->cleanup();
}
void
SWGAndroidSDRDriverInputReport::init() {
sample_rate = 0;
m_sample_rate_isSet = false;
}
void
SWGAndroidSDRDriverInputReport::cleanup() {
}
SWGAndroidSDRDriverInputReport*
SWGAndroidSDRDriverInputReport::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGAndroidSDRDriverInputReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&sample_rate, pJson["sampleRate"], "qint32", "");
}
QString
SWGAndroidSDRDriverInputReport::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGAndroidSDRDriverInputReport::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_sample_rate_isSet){
obj->insert("sampleRate", QJsonValue(sample_rate));
}
return obj;
}
qint32
SWGAndroidSDRDriverInputReport::getSampleRate() {
return sample_rate;
}
void
SWGAndroidSDRDriverInputReport::setSampleRate(qint32 sample_rate) {
this->sample_rate = sample_rate;
this->m_sample_rate_isSet = true;
}
bool
SWGAndroidSDRDriverInputReport::isSet(){
bool isObjectUpdated = false;
do{
if(m_sample_rate_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,58 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 7.0.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/*
* SWGAndroidSDRDriverInputReport.h
*
* AndroidSDRDriverInput
*/
#ifndef SWGAndroidSDRDriverInputReport_H_
#define SWGAndroidSDRDriverInputReport_H_
#include <QJsonObject>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGAndroidSDRDriverInputReport: public SWGObject {
public:
SWGAndroidSDRDriverInputReport();
SWGAndroidSDRDriverInputReport(QString* json);
virtual ~SWGAndroidSDRDriverInputReport();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGAndroidSDRDriverInputReport* fromJson(QString &jsonString) override;
qint32 getSampleRate();
void setSampleRate(qint32 sample_rate);
virtual bool isSet() override;
private:
qint32 sample_rate;
bool m_sample_rate_isSet;
};
}
#endif /* SWGAndroidSDRDriverInputReport_H_ */

View File

@ -0,0 +1,478 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 7.0.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
#include "SWGAndroidSDRDriverInputSettings.h"
#include "SWGHelpers.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QObject>
#include <QDebug>
namespace SWGSDRangel {
SWGAndroidSDRDriverInputSettings::SWGAndroidSDRDriverInputSettings(QString* json) {
init();
this->fromJson(*json);
}
SWGAndroidSDRDriverInputSettings::SWGAndroidSDRDriverInputSettings() {
center_frequency = 0L;
m_center_frequency_isSet = false;
lo_ppm_correction = 0;
m_lo_ppm_correction_isSet = false;
dc_block = 0;
m_dc_block_isSet = false;
iq_correction = 0;
m_iq_correction_isSet = false;
bias_tee = 0;
m_bias_tee_isSet = false;
direct_sampling = 0;
m_direct_sampling_isSet = false;
dev_sample_rate = 0;
m_dev_sample_rate_isSet = false;
log2_decim = 0;
m_log2_decim_isSet = false;
gain = 0;
m_gain_isSet = false;
agc = 0;
m_agc_isSet = false;
rf_bw = 0;
m_rf_bw_isSet = false;
sample_bits = 0;
m_sample_bits_isSet = false;
data_port = 0;
m_data_port_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = nullptr;
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
}
SWGAndroidSDRDriverInputSettings::~SWGAndroidSDRDriverInputSettings() {
this->cleanup();
}
void
SWGAndroidSDRDriverInputSettings::init() {
center_frequency = 0L;
m_center_frequency_isSet = false;
lo_ppm_correction = 0;
m_lo_ppm_correction_isSet = false;
dc_block = 0;
m_dc_block_isSet = false;
iq_correction = 0;
m_iq_correction_isSet = false;
bias_tee = 0;
m_bias_tee_isSet = false;
direct_sampling = 0;
m_direct_sampling_isSet = false;
dev_sample_rate = 0;
m_dev_sample_rate_isSet = false;
log2_decim = 0;
m_log2_decim_isSet = false;
gain = 0;
m_gain_isSet = false;
agc = 0;
m_agc_isSet = false;
rf_bw = 0;
m_rf_bw_isSet = false;
sample_bits = 0;
m_sample_bits_isSet = false;
data_port = 0;
m_data_port_isSet = false;
use_reverse_api = 0;
m_use_reverse_api_isSet = false;
reverse_api_address = new QString("");
m_reverse_api_address_isSet = false;
reverse_api_port = 0;
m_reverse_api_port_isSet = false;
reverse_api_device_index = 0;
m_reverse_api_device_index_isSet = false;
}
void
SWGAndroidSDRDriverInputSettings::cleanup() {
if(reverse_api_address != nullptr) {
delete reverse_api_address;
}
}
SWGAndroidSDRDriverInputSettings*
SWGAndroidSDRDriverInputSettings::fromJson(QString &json) {
QByteArray array (json.toStdString().c_str());
QJsonDocument doc = QJsonDocument::fromJson(array);
QJsonObject jsonObject = doc.object();
this->fromJsonObject(jsonObject);
return this;
}
void
SWGAndroidSDRDriverInputSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&center_frequency, pJson["centerFrequency"], "qint64", "");
::SWGSDRangel::setValue(&lo_ppm_correction, pJson["loPpmCorrection"], "qint32", "");
::SWGSDRangel::setValue(&dc_block, pJson["dcBlock"], "qint32", "");
::SWGSDRangel::setValue(&iq_correction, pJson["iqCorrection"], "qint32", "");
::SWGSDRangel::setValue(&bias_tee, pJson["biasTee"], "qint32", "");
::SWGSDRangel::setValue(&direct_sampling, pJson["directSampling"], "qint32", "");
::SWGSDRangel::setValue(&dev_sample_rate, pJson["devSampleRate"], "qint32", "");
::SWGSDRangel::setValue(&log2_decim, pJson["log2Decim"], "qint32", "");
::SWGSDRangel::setValue(&gain, pJson["gain"], "qint32", "");
::SWGSDRangel::setValue(&agc, pJson["agc"], "qint32", "");
::SWGSDRangel::setValue(&rf_bw, pJson["rfBW"], "qint32", "");
::SWGSDRangel::setValue(&sample_bits, pJson["sampleBits"], "qint32", "");
::SWGSDRangel::setValue(&data_port, pJson["dataPort"], "qint32", "");
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
::SWGSDRangel::setValue(&reverse_api_port, pJson["reverseAPIPort"], "qint32", "");
::SWGSDRangel::setValue(&reverse_api_device_index, pJson["reverseAPIDeviceIndex"], "qint32", "");
}
QString
SWGAndroidSDRDriverInputSettings::asJson ()
{
QJsonObject* obj = this->asJsonObject();
QJsonDocument doc(*obj);
QByteArray bytes = doc.toJson();
delete obj;
return QString(bytes);
}
QJsonObject*
SWGAndroidSDRDriverInputSettings::asJsonObject() {
QJsonObject* obj = new QJsonObject();
if(m_center_frequency_isSet){
obj->insert("centerFrequency", QJsonValue(center_frequency));
}
if(m_lo_ppm_correction_isSet){
obj->insert("loPpmCorrection", QJsonValue(lo_ppm_correction));
}
if(m_dc_block_isSet){
obj->insert("dcBlock", QJsonValue(dc_block));
}
if(m_iq_correction_isSet){
obj->insert("iqCorrection", QJsonValue(iq_correction));
}
if(m_bias_tee_isSet){
obj->insert("biasTee", QJsonValue(bias_tee));
}
if(m_direct_sampling_isSet){
obj->insert("directSampling", QJsonValue(direct_sampling));
}
if(m_dev_sample_rate_isSet){
obj->insert("devSampleRate", QJsonValue(dev_sample_rate));
}
if(m_log2_decim_isSet){
obj->insert("log2Decim", QJsonValue(log2_decim));
}
if(m_gain_isSet){
obj->insert("gain", QJsonValue(gain));
}
if(m_agc_isSet){
obj->insert("agc", QJsonValue(agc));
}
if(m_rf_bw_isSet){
obj->insert("rfBW", QJsonValue(rf_bw));
}
if(m_sample_bits_isSet){
obj->insert("sampleBits", QJsonValue(sample_bits));
}
if(m_data_port_isSet){
obj->insert("dataPort", QJsonValue(data_port));
}
if(m_use_reverse_api_isSet){
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
}
if(reverse_api_address != nullptr && *reverse_api_address != QString("")){
toJsonValue(QString("reverseAPIAddress"), reverse_api_address, obj, QString("QString"));
}
if(m_reverse_api_port_isSet){
obj->insert("reverseAPIPort", QJsonValue(reverse_api_port));
}
if(m_reverse_api_device_index_isSet){
obj->insert("reverseAPIDeviceIndex", QJsonValue(reverse_api_device_index));
}
return obj;
}
qint64
SWGAndroidSDRDriverInputSettings::getCenterFrequency() {
return center_frequency;
}
void
SWGAndroidSDRDriverInputSettings::setCenterFrequency(qint64 center_frequency) {
this->center_frequency = center_frequency;
this->m_center_frequency_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getLoPpmCorrection() {
return lo_ppm_correction;
}
void
SWGAndroidSDRDriverInputSettings::setLoPpmCorrection(qint32 lo_ppm_correction) {
this->lo_ppm_correction = lo_ppm_correction;
this->m_lo_ppm_correction_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getDcBlock() {
return dc_block;
}
void
SWGAndroidSDRDriverInputSettings::setDcBlock(qint32 dc_block) {
this->dc_block = dc_block;
this->m_dc_block_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getIqCorrection() {
return iq_correction;
}
void
SWGAndroidSDRDriverInputSettings::setIqCorrection(qint32 iq_correction) {
this->iq_correction = iq_correction;
this->m_iq_correction_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getBiasTee() {
return bias_tee;
}
void
SWGAndroidSDRDriverInputSettings::setBiasTee(qint32 bias_tee) {
this->bias_tee = bias_tee;
this->m_bias_tee_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getDirectSampling() {
return direct_sampling;
}
void
SWGAndroidSDRDriverInputSettings::setDirectSampling(qint32 direct_sampling) {
this->direct_sampling = direct_sampling;
this->m_direct_sampling_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getDevSampleRate() {
return dev_sample_rate;
}
void
SWGAndroidSDRDriverInputSettings::setDevSampleRate(qint32 dev_sample_rate) {
this->dev_sample_rate = dev_sample_rate;
this->m_dev_sample_rate_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getLog2Decim() {
return log2_decim;
}
void
SWGAndroidSDRDriverInputSettings::setLog2Decim(qint32 log2_decim) {
this->log2_decim = log2_decim;
this->m_log2_decim_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getGain() {
return gain;
}
void
SWGAndroidSDRDriverInputSettings::setGain(qint32 gain) {
this->gain = gain;
this->m_gain_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getAgc() {
return agc;
}
void
SWGAndroidSDRDriverInputSettings::setAgc(qint32 agc) {
this->agc = agc;
this->m_agc_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getRfBw() {
return rf_bw;
}
void
SWGAndroidSDRDriverInputSettings::setRfBw(qint32 rf_bw) {
this->rf_bw = rf_bw;
this->m_rf_bw_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getSampleBits() {
return sample_bits;
}
void
SWGAndroidSDRDriverInputSettings::setSampleBits(qint32 sample_bits) {
this->sample_bits = sample_bits;
this->m_sample_bits_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getDataPort() {
return data_port;
}
void
SWGAndroidSDRDriverInputSettings::setDataPort(qint32 data_port) {
this->data_port = data_port;
this->m_data_port_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getUseReverseApi() {
return use_reverse_api;
}
void
SWGAndroidSDRDriverInputSettings::setUseReverseApi(qint32 use_reverse_api) {
this->use_reverse_api = use_reverse_api;
this->m_use_reverse_api_isSet = true;
}
QString*
SWGAndroidSDRDriverInputSettings::getReverseApiAddress() {
return reverse_api_address;
}
void
SWGAndroidSDRDriverInputSettings::setReverseApiAddress(QString* reverse_api_address) {
this->reverse_api_address = reverse_api_address;
this->m_reverse_api_address_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getReverseApiPort() {
return reverse_api_port;
}
void
SWGAndroidSDRDriverInputSettings::setReverseApiPort(qint32 reverse_api_port) {
this->reverse_api_port = reverse_api_port;
this->m_reverse_api_port_isSet = true;
}
qint32
SWGAndroidSDRDriverInputSettings::getReverseApiDeviceIndex() {
return reverse_api_device_index;
}
void
SWGAndroidSDRDriverInputSettings::setReverseApiDeviceIndex(qint32 reverse_api_device_index) {
this->reverse_api_device_index = reverse_api_device_index;
this->m_reverse_api_device_index_isSet = true;
}
bool
SWGAndroidSDRDriverInputSettings::isSet(){
bool isObjectUpdated = false;
do{
if(m_center_frequency_isSet){
isObjectUpdated = true; break;
}
if(m_lo_ppm_correction_isSet){
isObjectUpdated = true; break;
}
if(m_dc_block_isSet){
isObjectUpdated = true; break;
}
if(m_iq_correction_isSet){
isObjectUpdated = true; break;
}
if(m_bias_tee_isSet){
isObjectUpdated = true; break;
}
if(m_direct_sampling_isSet){
isObjectUpdated = true; break;
}
if(m_dev_sample_rate_isSet){
isObjectUpdated = true; break;
}
if(m_log2_decim_isSet){
isObjectUpdated = true; break;
}
if(m_gain_isSet){
isObjectUpdated = true; break;
}
if(m_agc_isSet){
isObjectUpdated = true; break;
}
if(m_rf_bw_isSet){
isObjectUpdated = true; break;
}
if(m_sample_bits_isSet){
isObjectUpdated = true; break;
}
if(m_data_port_isSet){
isObjectUpdated = true; break;
}
if(m_use_reverse_api_isSet){
isObjectUpdated = true; break;
}
if(reverse_api_address && *reverse_api_address != QString("")){
isObjectUpdated = true; break;
}
if(m_reverse_api_port_isSet){
isObjectUpdated = true; break;
}
if(m_reverse_api_device_index_isSet){
isObjectUpdated = true; break;
}
}while(false);
return isObjectUpdated;
}
}

View File

@ -0,0 +1,155 @@
/**
* SDRangel
* This is the web REST/JSON API of SDRangel SDR software. SDRangel is an Open Source Qt5/OpenGL 3.0+ (4.3+ in Windows) GUI and server Software Defined Radio and signal analyzer in software. It supports Airspy, BladeRF, HackRF, LimeSDR, PlutoSDR, RTL-SDR, SDRplay RSP1 and FunCube --- Limitations and specifcities: * In SDRangel GUI the first Rx device set cannot be deleted. Conversely the server starts with no device sets and its number of device sets can be reduced to zero by as many calls as necessary to /sdrangel/deviceset with DELETE method. * Preset import and export from/to file is a server only feature. * Device set focus is a GUI only feature. * The following channels are not implemented (status 501 is returned): ATV and DATV demodulators, Channel Analyzer NG, LoRa demodulator * The device settings and report structures contains only the sub-structure corresponding to the device type. The DeviceSettings and DeviceReport structures documented here shows all of them but only one will be or should be present at a time * The channel settings and report structures contains only the sub-structure corresponding to the channel type. The ChannelSettings and ChannelReport structures documented here shows all of them but only one will be or should be present at a time ---
*
* OpenAPI spec version: 7.0.0
* Contact: f4exb06@gmail.com
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
/*
* SWGAndroidSDRDriverInputSettings.h
*
* AndroidSDRDriverInput
*/
#ifndef SWGAndroidSDRDriverInputSettings_H_
#define SWGAndroidSDRDriverInputSettings_H_
#include <QJsonObject>
#include <QString>
#include "SWGObject.h"
#include "export.h"
namespace SWGSDRangel {
class SWG_API SWGAndroidSDRDriverInputSettings: public SWGObject {
public:
SWGAndroidSDRDriverInputSettings();
SWGAndroidSDRDriverInputSettings(QString* json);
virtual ~SWGAndroidSDRDriverInputSettings();
void init();
void cleanup();
virtual QString asJson () override;
virtual QJsonObject* asJsonObject() override;
virtual void fromJsonObject(QJsonObject &json) override;
virtual SWGAndroidSDRDriverInputSettings* fromJson(QString &jsonString) override;
qint64 getCenterFrequency();
void setCenterFrequency(qint64 center_frequency);
qint32 getLoPpmCorrection();
void setLoPpmCorrection(qint32 lo_ppm_correction);
qint32 getDcBlock();
void setDcBlock(qint32 dc_block);
qint32 getIqCorrection();
void setIqCorrection(qint32 iq_correction);
qint32 getBiasTee();
void setBiasTee(qint32 bias_tee);
qint32 getDirectSampling();
void setDirectSampling(qint32 direct_sampling);
qint32 getDevSampleRate();
void setDevSampleRate(qint32 dev_sample_rate);
qint32 getLog2Decim();
void setLog2Decim(qint32 log2_decim);
qint32 getGain();
void setGain(qint32 gain);
qint32 getAgc();
void setAgc(qint32 agc);
qint32 getRfBw();
void setRfBw(qint32 rf_bw);
qint32 getSampleBits();
void setSampleBits(qint32 sample_bits);
qint32 getDataPort();
void setDataPort(qint32 data_port);
qint32 getUseReverseApi();
void setUseReverseApi(qint32 use_reverse_api);
QString* getReverseApiAddress();
void setReverseApiAddress(QString* reverse_api_address);
qint32 getReverseApiPort();
void setReverseApiPort(qint32 reverse_api_port);
qint32 getReverseApiDeviceIndex();
void setReverseApiDeviceIndex(qint32 reverse_api_device_index);
virtual bool isSet() override;
private:
qint64 center_frequency;
bool m_center_frequency_isSet;
qint32 lo_ppm_correction;
bool m_lo_ppm_correction_isSet;
qint32 dc_block;
bool m_dc_block_isSet;
qint32 iq_correction;
bool m_iq_correction_isSet;
qint32 bias_tee;
bool m_bias_tee_isSet;
qint32 direct_sampling;
bool m_direct_sampling_isSet;
qint32 dev_sample_rate;
bool m_dev_sample_rate_isSet;
qint32 log2_decim;
bool m_log2_decim_isSet;
qint32 gain;
bool m_gain_isSet;
qint32 agc;
bool m_agc_isSet;
qint32 rf_bw;
bool m_rf_bw_isSet;
qint32 sample_bits;
bool m_sample_bits_isSet;
qint32 data_port;
bool m_data_port_isSet;
qint32 use_reverse_api;
bool m_use_reverse_api_isSet;
QString* reverse_api_address;
bool m_reverse_api_address_isSet;
qint32 reverse_api_port;
bool m_reverse_api_port_isSet;
qint32 reverse_api_device_index;
bool m_reverse_api_device_index_isSet;
};
}
#endif /* SWGAndroidSDRDriverInputSettings_H_ */

View File

@ -36,6 +36,8 @@ SWGDeviceReport::SWGDeviceReport() {
m_airspy_report_isSet = false;
airspy_hf_report = nullptr;
m_airspy_hf_report_isSet = false;
android_sdr_driver_input_report = nullptr;
m_android_sdr_driver_input_report_isSet = false;
blade_rf2_input_report = nullptr;
m_blade_rf2_input_report_isSet = false;
blade_rf2_output_report = nullptr;
@ -112,6 +114,8 @@ SWGDeviceReport::init() {
m_airspy_report_isSet = false;
airspy_hf_report = new SWGAirspyHFReport();
m_airspy_hf_report_isSet = false;
android_sdr_driver_input_report = new SWGAndroidSDRDriverInputReport();
m_android_sdr_driver_input_report_isSet = false;
blade_rf2_input_report = new SWGBladeRF2InputReport();
m_blade_rf2_input_report_isSet = false;
blade_rf2_output_report = new SWGBladeRF2OutputReport();
@ -186,6 +190,9 @@ SWGDeviceReport::cleanup() {
if(airspy_hf_report != nullptr) {
delete airspy_hf_report;
}
if(android_sdr_driver_input_report != nullptr) {
delete android_sdr_driver_input_report;
}
if(blade_rf2_input_report != nullptr) {
delete blade_rf2_input_report;
}
@ -297,6 +304,8 @@ SWGDeviceReport::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&airspy_hf_report, pJson["airspyHFReport"], "SWGAirspyHFReport", "SWGAirspyHFReport");
::SWGSDRangel::setValue(&android_sdr_driver_input_report, pJson["androidSDRDriverInputReport"], "SWGAndroidSDRDriverInputReport", "SWGAndroidSDRDriverInputReport");
::SWGSDRangel::setValue(&blade_rf2_input_report, pJson["bladeRF2InputReport"], "SWGBladeRF2InputReport", "SWGBladeRF2InputReport");
::SWGSDRangel::setValue(&blade_rf2_output_report, pJson["bladeRF2OutputReport"], "SWGBladeRF2OutputReport", "SWGBladeRF2OutputReport");
@ -385,6 +394,9 @@ SWGDeviceReport::asJsonObject() {
if((airspy_hf_report != nullptr) && (airspy_hf_report->isSet())){
toJsonValue(QString("airspyHFReport"), airspy_hf_report, obj, QString("SWGAirspyHFReport"));
}
if((android_sdr_driver_input_report != nullptr) && (android_sdr_driver_input_report->isSet())){
toJsonValue(QString("androidSDRDriverInputReport"), android_sdr_driver_input_report, obj, QString("SWGAndroidSDRDriverInputReport"));
}
if((blade_rf2_input_report != nullptr) && (blade_rf2_input_report->isSet())){
toJsonValue(QString("bladeRF2InputReport"), blade_rf2_input_report, obj, QString("SWGBladeRF2InputReport"));
}
@ -519,6 +531,16 @@ SWGDeviceReport::setAirspyHfReport(SWGAirspyHFReport* airspy_hf_report) {
this->m_airspy_hf_report_isSet = true;
}
SWGAndroidSDRDriverInputReport*
SWGDeviceReport::getAndroidSdrDriverInputReport() {
return android_sdr_driver_input_report;
}
void
SWGDeviceReport::setAndroidSdrDriverInputReport(SWGAndroidSDRDriverInputReport* android_sdr_driver_input_report) {
this->android_sdr_driver_input_report = android_sdr_driver_input_report;
this->m_android_sdr_driver_input_report_isSet = true;
}
SWGBladeRF2InputReport*
SWGDeviceReport::getBladeRf2InputReport() {
return blade_rf2_input_report;
@ -836,6 +858,9 @@ SWGDeviceReport::isSet(){
if(airspy_hf_report && airspy_hf_report->isSet()){
isObjectUpdated = true; break;
}
if(android_sdr_driver_input_report && android_sdr_driver_input_report->isSet()){
isObjectUpdated = true; break;
}
if(blade_rf2_input_report && blade_rf2_input_report->isSet()){
isObjectUpdated = true; break;
}

View File

@ -26,6 +26,7 @@
#include "SWGAaroniaRTSAReport.h"
#include "SWGAirspyHFReport.h"
#include "SWGAirspyReport.h"
#include "SWGAndroidSDRDriverInputReport.h"
#include "SWGBladeRF2InputReport.h"
#include "SWGBladeRF2MIMOReport.h"
#include "SWGBladeRF2OutputReport.h"
@ -85,6 +86,9 @@ public:
SWGAirspyHFReport* getAirspyHfReport();
void setAirspyHfReport(SWGAirspyHFReport* airspy_hf_report);
SWGAndroidSDRDriverInputReport* getAndroidSdrDriverInputReport();
void setAndroidSdrDriverInputReport(SWGAndroidSDRDriverInputReport* android_sdr_driver_input_report);
SWGBladeRF2InputReport* getBladeRf2InputReport();
void setBladeRf2InputReport(SWGBladeRF2InputReport* blade_rf2_input_report);
@ -191,6 +195,9 @@ private:
SWGAirspyHFReport* airspy_hf_report;
bool m_airspy_hf_report_isSet;
SWGAndroidSDRDriverInputReport* android_sdr_driver_input_report;
bool m_android_sdr_driver_input_report_isSet;
SWGBladeRF2InputReport* blade_rf2_input_report;
bool m_blade_rf2_input_report_isSet;

View File

@ -38,6 +38,8 @@ SWGDeviceSettings::SWGDeviceSettings() {
m_airspy_settings_isSet = false;
airspy_hf_settings = nullptr;
m_airspy_hf_settings_isSet = false;
android_sdr_driver_input_settings = nullptr;
m_android_sdr_driver_input_settings_isSet = false;
audio_catsiso_settings = nullptr;
m_audio_catsiso_settings_isSet = false;
audio_input_settings = nullptr;
@ -144,6 +146,8 @@ SWGDeviceSettings::init() {
m_airspy_settings_isSet = false;
airspy_hf_settings = new SWGAirspyHFSettings();
m_airspy_hf_settings_isSet = false;
android_sdr_driver_input_settings = new SWGAndroidSDRDriverInputSettings();
m_android_sdr_driver_input_settings_isSet = false;
audio_catsiso_settings = new SWGAudioCATSISOSettings();
m_audio_catsiso_settings_isSet = false;
audio_input_settings = new SWGAudioInputSettings();
@ -247,6 +251,9 @@ SWGDeviceSettings::cleanup() {
if(airspy_hf_settings != nullptr) {
delete airspy_hf_settings;
}
if(android_sdr_driver_input_settings != nullptr) {
delete android_sdr_driver_input_settings;
}
if(audio_catsiso_settings != nullptr) {
delete audio_catsiso_settings;
}
@ -402,6 +409,8 @@ SWGDeviceSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&airspy_hf_settings, pJson["airspyHFSettings"], "SWGAirspyHFSettings", "SWGAirspyHFSettings");
::SWGSDRangel::setValue(&android_sdr_driver_input_settings, pJson["androidSDRDriverInputSettings"], "SWGAndroidSDRDriverInputSettings", "SWGAndroidSDRDriverInputSettings");
::SWGSDRangel::setValue(&audio_catsiso_settings, pJson["audioCATSISOSettings"], "SWGAudioCATSISOSettings", "SWGAudioCATSISOSettings");
::SWGSDRangel::setValue(&audio_input_settings, pJson["audioInputSettings"], "SWGAudioInputSettings", "SWGAudioInputSettings");
@ -521,6 +530,9 @@ SWGDeviceSettings::asJsonObject() {
if((airspy_hf_settings != nullptr) && (airspy_hf_settings->isSet())){
toJsonValue(QString("airspyHFSettings"), airspy_hf_settings, obj, QString("SWGAirspyHFSettings"));
}
if((android_sdr_driver_input_settings != nullptr) && (android_sdr_driver_input_settings->isSet())){
toJsonValue(QString("androidSDRDriverInputSettings"), android_sdr_driver_input_settings, obj, QString("SWGAndroidSDRDriverInputSettings"));
}
if((audio_catsiso_settings != nullptr) && (audio_catsiso_settings->isSet())){
toJsonValue(QString("audioCATSISOSettings"), audio_catsiso_settings, obj, QString("SWGAudioCATSISOSettings"));
}
@ -707,6 +719,16 @@ SWGDeviceSettings::setAirspyHfSettings(SWGAirspyHFSettings* airspy_hf_settings)
this->m_airspy_hf_settings_isSet = true;
}
SWGAndroidSDRDriverInputSettings*
SWGDeviceSettings::getAndroidSdrDriverInputSettings() {
return android_sdr_driver_input_settings;
}
void
SWGDeviceSettings::setAndroidSdrDriverInputSettings(SWGAndroidSDRDriverInputSettings* android_sdr_driver_input_settings) {
this->android_sdr_driver_input_settings = android_sdr_driver_input_settings;
this->m_android_sdr_driver_input_settings_isSet = true;
}
SWGAudioCATSISOSettings*
SWGDeviceSettings::getAudioCatsisoSettings() {
return audio_catsiso_settings;
@ -1167,6 +1189,9 @@ SWGDeviceSettings::isSet(){
if(airspy_hf_settings && airspy_hf_settings->isSet()){
isObjectUpdated = true; break;
}
if(android_sdr_driver_input_settings && android_sdr_driver_input_settings->isSet()){
isObjectUpdated = true; break;
}
if(audio_catsiso_settings && audio_catsiso_settings->isSet()){
isObjectUpdated = true; break;
}

View File

@ -26,6 +26,7 @@
#include "SWGAaroniaRTSASettings.h"
#include "SWGAirspyHFSettings.h"
#include "SWGAirspySettings.h"
#include "SWGAndroidSDRDriverInputSettings.h"
#include "SWGAudioCATSISOSettings.h"
#include "SWGAudioInputSettings.h"
#include "SWGAudioOutputSettings.h"
@ -103,6 +104,9 @@ public:
SWGAirspyHFSettings* getAirspyHfSettings();
void setAirspyHfSettings(SWGAirspyHFSettings* airspy_hf_settings);
SWGAndroidSDRDriverInputSettings* getAndroidSdrDriverInputSettings();
void setAndroidSdrDriverInputSettings(SWGAndroidSDRDriverInputSettings* android_sdr_driver_input_settings);
SWGAudioCATSISOSettings* getAudioCatsisoSettings();
void setAudioCatsisoSettings(SWGAudioCATSISOSettings* audio_catsiso_settings);
@ -254,6 +258,9 @@ private:
SWGAirspyHFSettings* airspy_hf_settings;
bool m_airspy_hf_settings_isSet;
SWGAndroidSDRDriverInputSettings* android_sdr_driver_input_settings;
bool m_android_sdr_driver_input_settings_isSet;
SWGAudioCATSISOSettings* audio_catsiso_settings;
bool m_audio_catsiso_settings_isSet;

View File

@ -51,6 +51,8 @@
#include "SWGAirspyHFSettings.h"
#include "SWGAirspyReport.h"
#include "SWGAirspySettings.h"
#include "SWGAndroidSDRDriverInputReport.h"
#include "SWGAndroidSDRDriverInputSettings.h"
#include "SWGAntennaToolsSettings.h"
#include "SWGArgInfo.h"
#include "SWGArgValue.h"
@ -552,6 +554,16 @@ namespace SWGSDRangel {
obj->init();
return obj;
}
if(QString("SWGAndroidSDRDriverInputReport").compare(type) == 0) {
SWGAndroidSDRDriverInputReport *obj = new SWGAndroidSDRDriverInputReport();
obj->init();
return obj;
}
if(QString("SWGAndroidSDRDriverInputSettings").compare(type) == 0) {
SWGAndroidSDRDriverInputSettings *obj = new SWGAndroidSDRDriverInputSettings();
obj->init();
return obj;
}
if(QString("SWGAntennaToolsSettings").compare(type) == 0) {
SWGAntennaToolsSettings *obj = new SWGAntennaToolsSettings();
obj->init();