Merge branch 'wfserver'

merge-requests/9/merge
Roeland Jansen 2022-05-15 13:11:35 +02:00
commit 49773706d7
15 zmienionych plików z 157 dodań i 108 usunięć

Wyświetl plik

@ -43,28 +43,28 @@ class audioHandler : public QObject
Q_OBJECT
public:
explicit audioHandler(QObject* parent = nullptr);
~audioHandler();
audioHandler(QObject* parent = nullptr);
virtual ~audioHandler();
int getLatency();
virtual int getLatency();
void start();
void stop();
virtual void start();
virtual void stop();
quint16 getAmplitude();
virtual quint16 getAmplitude();
public slots:
bool init(audioSetup setup);
void changeLatency(const quint16 newSize);
void setVolume(unsigned char volume);
void incomingAudio(const audioPacket data);
void convertedInput(audioPacket audio);
void convertedOutput(audioPacket audio);
virtual bool init(audioSetup setup);
virtual void changeLatency(const quint16 newSize);
virtual void setVolume(unsigned char volume);
virtual void incomingAudio(const audioPacket data);
virtual void convertedInput(audioPacket audio);
virtual void convertedOutput(audioPacket audio);
private slots:
void stateChanged(QAudio::State state);
void clearUnderrun();
void getNextAudioChunk();
virtual void stateChanged(QAudio::State state);
virtual void clearUnderrun();
virtual void getNextAudioChunk();
signals:
void audioMessage(QString message);
@ -82,7 +82,7 @@ private:
bool isUnderrun = false;
bool isOverrun = true;
bool isOverrun = false;
bool isInitialized=false;
bool isReady = false;
bool audioBuffered = false;
@ -113,7 +113,7 @@ private:
volatile bool ready = false;
audioPacket tempBuf;
quint16 currentLatency;
float amplitude;
float amplitude=0.0;
qreal volume = 1.0;
audioSetup setup;

Wyświetl plik

@ -8,12 +8,6 @@
commHandler::commHandler(QObject* parent) : QObject(parent)
{
//constructor
// grab baud rate and other comm port details
// if they need to be changed later, please
// destroy this and create a new one.
port = new QSerialPort();
// TODO: The following should become arguments and/or functions
// Add signal/slot everywhere for comm port setup.
// Consider how to "re-setup" and how to save the state for next time.
@ -22,13 +16,7 @@ commHandler::commHandler(QObject* parent) : QObject(parent)
portName = "/dev/ttyUSB0";
this->PTTviaRTS = false;
setupComm(); // basic parameters
openPort();
//qInfo(logSerial()) << "Serial buffer size: " << port->readBufferSize();
//port->setReadBufferSize(1024); // manually. 256 never saw any return from the radio. why...
//qInfo(logSerial()) << "Serial buffer size: " << port->readBufferSize();
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn()));
init();
}
commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QObject* parent) : QObject(parent)
@ -38,7 +26,6 @@ commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QO
// if they need to be changed later, please
// destroy this and create a new one.
port = new QSerialPort();
if (wfFormat == 1) { // Single waterfall packet
combineWf = true;
@ -52,7 +39,19 @@ commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QO
stopbits = 1;
this->portName = portName;
this->PTTviaRTS = false;
init();
}
void commHandler::init()
{
if (port != Q_NULLPTR) {
delete port;
port = Q_NULLPTR;
isConnected = false;
}
port = new QSerialPort();
setupComm(); // basic parameters
openPort();
// qInfo(logSerial()) << "Serial buffer size: " << port->readBufferSize();
@ -60,9 +59,10 @@ commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QO
//qInfo(logSerial()) << "Serial buffer size: " << port->readBufferSize();
connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn()));
connect(port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError)));
lastDataReceived = QTime::currentTime();
}
commHandler::~commHandler()
{
qInfo(logSerial()) << "Closing serial port: " << port->portName();
@ -87,16 +87,16 @@ void commHandler::receiveDataFromUserToRig(const QByteArray &data)
void commHandler::sendDataOut(const QByteArray &writeData)
{
mutex.lock();
// Recycle port to attempt reconnection.
if (!this->isConnected) {
closePort();
openPort();
}
if (!this->isConnected) {
if (lastDataReceived.msecsTo(QTime::currentTime()) > 2000) {
qDebug(logSerial()) << "Serial port error? Attempting reconnect...";
lastDataReceived = QTime::currentTime();
QTimer::singleShot(500, this, SLOT(init()));
return;
}
mutex.lock();
qint64 bytesWritten;
if(PTTviaRTS)
@ -143,7 +143,7 @@ void commHandler::sendDataOut(const QByteArray &writeData)
}
bytesWritten = port->write(writeData);
if(bytesWritten != (qint64)writeData.size())
{
qDebug(logSerial()) << "bytesWritten: " << bytesWritten << " length of byte array: " << writeData.length()\
@ -162,6 +162,7 @@ void commHandler::receiveDataIn()
// because we know what constitutes a valid "frame" of data.
// new code:
lastDataReceived = QTime::currentTime();
port->startTransaction();
inPortData = port->readAll();
@ -371,3 +372,17 @@ void commHandler::printHex(const QByteArray &pdata, bool printVert, bool printHo
}
void commHandler::handleError(QSerialPort::SerialPortError err)
{
switch (err) {
case QSerialPort::NoError:
break;
default:
if (lastDataReceived.msecsTo(QTime::currentTime()) > 2000) {
qDebug(logSerial()) << "Serial port" << port->portName() << "Error, attempting disconnect/reconnect";
lastDataReceived = QTime::currentTime();
QTimer::singleShot(500, this, SLOT(init()));
}
break;
}
}

Wyświetl plik

@ -6,6 +6,8 @@
#include <QMutex>
#include <QDataStream>
#include <QtSerialPort/QSerialPort>
#include <QTime>
#include <QTimer>
// This class abstracts the comm port in a useful way and connects to
// the command creator and command parser.
@ -25,6 +27,8 @@ public:
public slots:
void setUseRTSforPTT(bool useRTS);
void setRTS(bool rtsOn);
void handleError(QSerialPort::SerialPortError error);
void init();
private slots:
void receiveDataIn(); // from physical port
@ -58,7 +62,7 @@ private:
unsigned char buffer[256];
QString portName;
QSerialPort *port;
QSerialPort *port=Q_NULLPTR;
qint32 baudrate;
unsigned char stopbits;
bool rolledBack;
@ -82,6 +86,7 @@ private:
quint8 spectrumInformation;
quint8 spectrumOutOfRange;
quint8 lastSpectrum = 0;
QTime lastDataReceived;
};
#endif // COMMHANDLER_H

Wyświetl plik

@ -217,7 +217,11 @@ bool paHandler::init(audioSetup setup)
void paHandler::setVolume(unsigned char volume)
{
#ifdef Q_OS_WIN
this->volume = audiopot[volume] * 5;
#else
this->volume = audiopot[volume];
#endif
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "setVolume: " << volume << "(" << this->volume << ")";
}
@ -246,6 +250,18 @@ int paHandler::writeData(const void* inputBuffer, void* outputBuffer,
packet.data.append((char*)inputBuffer, nFrames*inFormat.channelCount()*sizeof(float));
emit sendToConverter(packet);
if (status == paInputUnderflow) {
isUnderrun = true;
}
else if (status == paInputOverflow) {
isOverrun = true;
}
else
{
isUnderrun = false;
isOverrun = false;
}
return paContinue;
}
@ -261,44 +277,24 @@ void paHandler::convertedOutput(audioPacket packet) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Error writing audio!";
}
const PaStreamInfo* info = Pa_GetStreamInfo(audio);
//currentLatency = packet.time.msecsTo(QTime::currentTime()) + (info->outputLatency * 1000);
currentLatency = (info->outputLatency * 1000);
}
/*
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (outFormat.durationForBytes(audioOutput->bufferSize() - audioOutput->bytesFree()) / 1000);
if (audioDevice != Q_NULLPTR) {
if (audioDevice->write(packet.data) < packet.data.size()) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Buffer full!";
isOverrun = true;
}
else {
isOverrun = false;
}
if (lastReceived.msecsTo(QTime::currentTime()) > 100) {
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Time since last audio packet" << lastReceived.msecsTo(QTime::currentTime()) << "Expected around" << setup.blockSize;
}
lastReceived = QTime::currentTime();
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (info->outputLatency * 1000);
}
lastSentSeq = packet.seq;
*/
amplitude = packet.amplitude;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, false, false);
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
}
}
void paHandler::convertedInput(audioPacket audio)
void paHandler::convertedInput(audioPacket packet)
{
if (audio.data.size() > 0) {
emit haveAudioData(audio);
amplitude = audio.amplitude;
emit haveLevels(getAmplitude(), setup.latency, currentLatency, false,false);
if (packet.data.size() > 0) {
emit haveAudioData(packet);
amplitude = packet.amplitude;
const PaStreamInfo* info = Pa_GetStreamInfo(audio);
currentLatency = packet.time.msecsTo(QTime::currentTime()) + (info->inputLatency * 1000);
emit haveLevels(getAmplitude(), setup.latency, currentLatency, isUnderrun, isOverrun);
}
}
@ -317,5 +313,5 @@ int paHandler::getLatency()
quint16 paHandler::getAmplitude()
{
return amplitude;
return static_cast<quint16>(amplitude * 255.0);
}

Wyświetl plik

@ -18,6 +18,7 @@
/* Logarithmic taper for volume control */
#include "audiotaper.h"
#include "audiohandler.h"
/* Audio converter class*/
#include "audioconverter.h"
@ -25,7 +26,7 @@
#include <QDebug>
class paHandler : public QObject
class paHandler : public audioHandler
{
Q_OBJECT
@ -80,7 +81,7 @@ private:
quint32 lastSentSeq = 0;
quint16 currentLatency;
quint16 amplitude = 0;
float amplitude=0.0;
qreal volume = 1.0;
audioSetup setup;
@ -88,6 +89,8 @@ private:
QAudioFormat outFormat;
audioConverter* converter = Q_NULLPTR;
QThread* converterThread = Q_NULLPTR;
bool isUnderrun = false;
bool isOverrun = false;
};
#endif // PAHANDLER_H

Wyświetl plik

@ -20,7 +20,7 @@ rtHandler::~rtHandler()
audio->abortStream();
audio->closeStream();
}
catch (RtAudioError& e) {
catch (RtAudioError& e) {
qInfo(logAudio()) << "Error closing stream:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage());
}
delete audio;
@ -41,7 +41,7 @@ bool rtHandler::init(audioSetup setup)
}
this->setup = setup;
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "PortAudio handler starting:" << setup.name;
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "RTAudio handler starting:" << setup.name;
if (setup.portInt==-1)
{
@ -90,9 +90,9 @@ bool rtHandler::init(audioSetup setup)
try {
info = audio->getDeviceInfo(aParams.deviceId);
}
catch (RtAudioError& e) {
qInfo(logAudio()) << "Device error:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage());
return isInitialized;
catch (RtAudioError e) {
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Device exception:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage());
goto errorHandler;
}
if (info.probed)
@ -106,7 +106,7 @@ bool rtHandler::init(audioSetup setup)
if (info.nativeFormats == 0)
{
qCritical(logAudio()) << " No natively supported data formats!";
return false;
goto errorHandler;
}
else {
qDebug(logAudio()) << " Supported formats:" <<
@ -133,7 +133,7 @@ bool rtHandler::init(audioSetup setup)
else if (outFormat.channelCount() < 1)
{
qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << "No channels found, aborting setup.";
return false;
goto errorHandler;
}
aParams.nChannels = outFormat.channelCount();
@ -162,7 +162,7 @@ bool rtHandler::init(audioSetup setup)
}
else {
qCritical(logAudio()) << "Cannot find supported sample format!";
return false;
goto errorHandler;
}
}
@ -208,17 +208,33 @@ bool rtHandler::init(audioSetup setup)
}
catch (RtAudioError& e) {
qInfo(logAudio()) << "Error opening:" << QString::fromStdString(e.getMessage());
// Try again?
goto errorHandler;
}
}
else
{
qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") could not be probed, check audio configuration!";
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") could not be probed, check audio configuration!";
goto errorHandler;
}
this->setVolume(setup.localAFgain);
return isInitialized;
errorHandler:
if (retryConnectCount < 10) {
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "*** Attempting to reconnect to audio device in 500ms";
QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup));
retryConnectCount++;
}
else
{
qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << "*** Retry count exceeded, giving up!";
}
return false;
}
@ -334,5 +350,5 @@ int rtHandler::getLatency()
quint16 rtHandler::getAmplitude()
{
return amplitude;
return static_cast<quint16>(amplitude * 255.0);
}

Wyświetl plik

@ -6,7 +6,7 @@
#include <QThread>
#include <QMutex>
#ifdef Q_OS_WIN
#ifndef Q_OS_LINUX
#include "RtAudio.h"
#else
#include "rtaudio/RtAudio.h"
@ -16,6 +16,7 @@
#include <QAudioFormat>
#include <QTime>
#include <QMap>
#include <QTimer>
/* wfview Packet types */
@ -24,14 +25,14 @@
/* Logarithmic taper for volume control */
#include "audiotaper.h"
#include "audiohandler.h"
/* Audio converter class*/
#include "audioconverter.h"
#include <QDebug>
class rtHandler : public QObject
class rtHandler : public audioHandler
{
Q_OBJECT
@ -96,7 +97,7 @@ private:
quint32 lastSentSeq = 0;
quint16 currentLatency;
quint16 amplitude = 0;
float amplitude = 0.0;
qreal volume = 1.0;
audioSetup setup;
@ -106,8 +107,9 @@ private:
QThread* converterThread = Q_NULLPTR;
QByteArray arrayBuffer;
bool isUnderrun = false;
bool isOverrun = true;
bool isOverrun = false;
QMutex audioMutex;
int retryConnectCount = 0;
};
#endif // rtHandler_H

Wyświetl plik

@ -42,21 +42,29 @@ void selectRadio::setInUse(quint8 radio, quint8 busy, QString user, QString ip)
ui->table->setItem(radio, 3, new QTableWidgetItem(user));
ui->table->setItem(radio, 4, new QTableWidgetItem(ip));
for (int f = 0; f < 5; f++) {
if (busy == 1)
if (busy == 1)
{
ui->table->item(radio, f)->setBackground(Qt::darkGreen);
else if (busy == 2)
}
else if (busy == 2)
{
ui->table->item(radio, f)->setBackground(Qt::red);
}
else
{
ui->table->item(radio, f)->setBackground(Qt::black);
}
}
}
void selectRadio::on_table_cellClicked(int row, int col) {
qInfo() << "Clicked on " << row << "," << col;
ui->table->selectRow(row);
emit selectedRadio(row);
this->setVisible(false);
if (ui->table->item(row, col)->backgroundColor() != Qt::darkGreen) {
ui->table->selectRow(row);
emit selectedRadio(row);
this->setVisible(false);
}
}

Wyświetl plik

@ -89,7 +89,7 @@ void servermain::openRig()
{
//qInfo(logSystem()) << "Got rig";
QMetaObject::invokeMethod(radio->rig, [=]() {
radio->rig->commSetup(radio->civAddr, radio->serialPort, radio->baudRate, QString("none"),prefs.tcpPort,0);
radio->rig->commSetup(radio->civAddr, radio->serialPort, radio->baudRate, QString("none"),prefs.tcpPort,radio->waterfallFormat);
}, Qt::QueuedConnection);
}
}
@ -458,6 +458,7 @@ void servermain::loadSettings()
settings->setValue("SerialPortBaud", defPrefs.serialPortBaud);
settings->setValue("AudioInput", "default");
settings->setValue("AudioOutput", "default");
settings->setValue("WaterfallFormat", 0);
}
settings->endArray();
@ -497,6 +498,7 @@ void servermain::loadSettings()
tempPrefs->baudRate = (quint32)settings->value("SerialPortBaud", defPrefs.serialPortBaud).toInt();
tempPrefs->rxAudioSetup.name = settings->value("AudioInput", "default").toString();
tempPrefs->txAudioSetup.name = settings->value("AudioOutput", "default").toString();
tempPrefs->waterfallFormat = settings->value("WaterfallFormat", 0).toInt();
tempPrefs->rxAudioSetup.type = prefs.audioSystem;
tempPrefs->txAudioSetup.type = prefs.audioSystem;

Wyświetl plik

@ -69,10 +69,10 @@ private:
uint16_t sendAudioSeq = 0;
QObject* rxaudio = Q_NULLPTR;
audioHandler* rxaudio = Q_NULLPTR;
QThread* rxAudioThread = Q_NULLPTR;
QObject* txaudio = Q_NULLPTR;
audioHandler* txaudio = Q_NULLPTR;
QThread* txAudioThread = Q_NULLPTR;
QTimer* txAudioTimer = Q_NULLPTR;

Wyświetl plik

@ -395,13 +395,13 @@ void udpServer::controlReceived()
connect(radio->txAudioThread, SIGNAL(finished()), radio->txaudio, SLOT(deleteLater()));
// Not sure how we make this work in QT5.9?
#if (QT_VERSION >= QT_VERSION_CHECK(7,10,0))
QMetaObject::invokeMethod((audioHandler*)radio->txaudio, [=]() {
#if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
QMetaObject::invokeMethod(radio->txaudio, [=]() {
radio->txaudio->init(radio->txAudioSetup);
}, Qt::QueuedConnection);
#else
emit setupTxAudio(radio->txAudioSetup);
//#warning "QT 5.9 is not fully supported multiple rigs will NOT work!"
#warning "QT 5.9 is not fully supported multiple rigs will NOT work!"
#endif
hasTxAudio = datagram.senderAddress();
@ -442,7 +442,7 @@ void udpServer::controlReceived()
connect(radio->rxAudioThread, SIGNAL(finished()), radio->rxaudio, SLOT(deleteLater()));
connect(radio->rxaudio, SIGNAL(haveAudioData(audioPacket)), this, SLOT(receiveAudioData(audioPacket)));
#if (QT_VERSION >= QT_VERSION_CHECK(7,10,0))
#if (QT_VERSION >= QT_VERSION_CHECK(5,10,0))
QMetaObject::invokeMethod(radio->rxaudio, [=]() {
radio->rxaudio->init(radio->rxAudioSetup);
}, Qt::QueuedConnection);

Wyświetl plik

@ -70,12 +70,13 @@ struct RIGCONFIG {
rigCapabilities rigCaps;
rigCommander* rig = Q_NULLPTR;
QThread* rigThread = Q_NULLPTR;
QObject* rxaudio = Q_NULLPTR;
audioHandler* rxaudio = Q_NULLPTR;
QThread* rxAudioThread = Q_NULLPTR;
QObject* txaudio = Q_NULLPTR;
audioHandler* txaudio = Q_NULLPTR;
QThread* txAudioThread = Q_NULLPTR;
QTimer* rxAudioTimer = Q_NULLPTR;
QTimer* connectTimer = Q_NULLPTR;
quint8 waterfallFormat;
};

Wyświetl plik

@ -41,7 +41,7 @@
#include <memory>
#include <portaudio.h>
#ifdef Q_OS_WIN
#ifndef Q_OS_LINUX
#include "RtAudio.h"
#else
#include "rtaudio/RtAudio.h"
@ -914,4 +914,4 @@ Q_DECLARE_METATYPE(rigstate*)
#endif // WFMAIN_H
#endif
#endif

Wyświetl plik

@ -41,8 +41,8 @@ win32:DEFINES += __WINDOWS_WASAPI__
#linux:DEFINES += __LINUX_OSS__
linux:DEFINES += __LINUX_PULSE__
macx:DEFINES += __MACOSX_CORE__
win32:SOURCES += ../rtaudio/RTAudio.cpp
win32:HEADERS += ../rtaudio/RTAUdio.h
!linux:SOURCES += ../rtaudio/RTAudio.cpp
!linux:HEADERS += ../rtaudio/RTAUdio.h
!linux:INCLUDEPATH += ../rtaudio
linux:LIBS += -lpulse -lpulse-simple -lrtaudio -lpthread

Wyświetl plik

@ -38,9 +38,10 @@ win32:DEFINES += __WINDOWS_WASAPI__
#linux:DEFINES += __LINUX_OSS__
linux:DEFINES += __LINUX_PULSE__
macx:DEFINES += __MACOSX_CORE__
win32:SOURCES += ../rtaudio/RTAudio.cpp
win32:HEADERS += ../rtaudio/RTAUdio.h
!linux:SOURCES += ../rtaudio/RTAudio.cpp
!linux:HEADERS += ../rtaudio/RTAUdio.h
!linux:INCLUDEPATH += ../rtaudio
linux:LIBS += -lpulse -lpulse-simple -lrtaudio -lpthread
win32:INCLUDEPATH += ../portaudio/include