From b78f613ef2fd9ca75cdf1496621ccb4554d4c3c7 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 13 May 2022 16:09:26 +0100 Subject: [PATCH 01/23] Bit of code-tidying and minor fixes --- audiohandler.h | 2 +- pahandler.cpp | 54 +++++++++++++++++++++++--------------------------- pahandler.h | 2 ++ rthandler.h | 2 +- 4 files changed, 29 insertions(+), 31 deletions(-) diff --git a/audiohandler.h b/audiohandler.h index 47e6412..1f56b2b 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -82,7 +82,7 @@ private: bool isUnderrun = false; - bool isOverrun = true; + bool isOverrun = false; bool isInitialized=false; bool isReady = false; bool audioBuffered = false; diff --git a/pahandler.cpp b/pahandler.cpp index 6bd3875..646142f 100644 --- a/pahandler.cpp +++ b/pahandler.cpp @@ -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); } } diff --git a/pahandler.h b/pahandler.h index 5e311aa..f55a79f 100644 --- a/pahandler.h +++ b/pahandler.h @@ -88,6 +88,8 @@ private: QAudioFormat outFormat; audioConverter* converter = Q_NULLPTR; QThread* converterThread = Q_NULLPTR; + bool isUnderrun = false; + bool isOverrun = false; }; #endif // PAHANDLER_H diff --git a/rthandler.h b/rthandler.h index c78cf6c..e3461cc 100644 --- a/rthandler.h +++ b/rthandler.h @@ -106,7 +106,7 @@ private: QThread* converterThread = Q_NULLPTR; QByteArray arrayBuffer; bool isUnderrun = false; - bool isOverrun = true; + bool isOverrun = false; QMutex audioMutex; }; From c84cc4330d33e2fb7422a7a0310ba987d7cb138a Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Fri, 13 May 2022 18:45:13 +0100 Subject: [PATCH 02/23] Add waterfallFormat to wfserver --- servermain.cpp | 4 +++- udpserver.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/servermain.cpp b/servermain.cpp index dd4673c..c2942c5 100644 --- a/servermain.cpp +++ b/servermain.cpp @@ -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; diff --git a/udpserver.h b/udpserver.h index 7b98e7c..ff2e78d 100644 --- a/udpserver.h +++ b/udpserver.h @@ -76,6 +76,7 @@ struct RIGCONFIG { QThread* txAudioThread = Q_NULLPTR; QTimer* rxAudioTimer = Q_NULLPTR; QTimer* connectTimer = Q_NULLPTR; + quint8 waterfallFormat; }; From 8fd8fa390ef0b56746571c178af8acc60656f328 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 01:11:00 +0100 Subject: [PATCH 03/23] Fix mod meters in PA/RT --- audiohandler.h | 2 +- pahandler.cpp | 2 +- pahandler.h | 2 +- rthandler.cpp | 2 +- rthandler.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/audiohandler.h b/audiohandler.h index 1f56b2b..9c503ec 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -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; diff --git a/pahandler.cpp b/pahandler.cpp index 646142f..e0de0eb 100644 --- a/pahandler.cpp +++ b/pahandler.cpp @@ -313,5 +313,5 @@ int paHandler::getLatency() quint16 paHandler::getAmplitude() { - return amplitude; + return static_cast(amplitude * 255.0); } diff --git a/pahandler.h b/pahandler.h index f55a79f..cd55e95 100644 --- a/pahandler.h +++ b/pahandler.h @@ -80,7 +80,7 @@ private: quint32 lastSentSeq = 0; quint16 currentLatency; - quint16 amplitude = 0; + float amplitude=0.0; qreal volume = 1.0; audioSetup setup; diff --git a/rthandler.cpp b/rthandler.cpp index c6afb31..ea00958 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -334,5 +334,5 @@ int rtHandler::getLatency() quint16 rtHandler::getAmplitude() { - return amplitude; + return static_cast(amplitude * 255.0); } diff --git a/rthandler.h b/rthandler.h index e3461cc..5f34997 100644 --- a/rthandler.h +++ b/rthandler.h @@ -96,7 +96,7 @@ private: quint32 lastSentSeq = 0; quint16 currentLatency; - quint16 amplitude = 0; + float amplitude = 0.0; qreal volume = 1.0; audioSetup setup; From 48562aa23b01f7e6b516448854f2adc7360ec0ce Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 01:11:15 +0100 Subject: [PATCH 04/23] Don't try to connect to radio we are already connected to --- selectradio.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/selectradio.cpp b/selectradio.cpp index 0862ace..61e0192 100644 --- a/selectradio.cpp +++ b/selectradio.cpp @@ -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); + } } From c1461947eb45afdd6b8d777404ff73152f6184fe Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 01:27:44 +0100 Subject: [PATCH 05/23] If audio device fails to open, retry 10 times before giving up. --- rthandler.cpp | 6 ++++++ rthandler.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/rthandler.cpp b/rthandler.cpp index ea00958..c710f8f 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -208,6 +208,12 @@ bool rtHandler::init(audioSetup setup) } catch (RtAudioError& e) { qInfo(logAudio()) << "Error opening:" << QString::fromStdString(e.getMessage()); + // Try again? + if (retryConnectCount < 10) { + QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); + retryConnectCount++; + return false; + } } } else diff --git a/rthandler.h b/rthandler.h index 5f34997..10acd78 100644 --- a/rthandler.h +++ b/rthandler.h @@ -16,6 +16,7 @@ #include #include #include +#include /* wfview Packet types */ @@ -108,6 +109,7 @@ private: bool isUnderrun = false; bool isOverrun = false; QMutex audioMutex; + int retryConnectCount = 0; }; #endif // rtHandler_H From 35d54468cd43760bb70d7f5ea0587eb73cf56acd Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 01:31:04 +0100 Subject: [PATCH 06/23] Update rthandler.cpp --- rthandler.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rthandler.cpp b/rthandler.cpp index c710f8f..1c10493 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -219,6 +219,11 @@ bool rtHandler::init(audioSetup setup) else { qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") could not be probed, check audio configuration!"; + if (retryConnectCount < 10) { + QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); + retryConnectCount++; + return false; + } } this->setVolume(setup.localAFgain); From 28a3209c2148072bfc20f26c85d6d742077a999a Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 01:37:03 +0100 Subject: [PATCH 07/23] Update rthandler.cpp --- rthandler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rthandler.cpp b/rthandler.cpp index 1c10493..a392c46 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -133,7 +133,11 @@ bool rtHandler::init(audioSetup setup) else if (outFormat.channelCount() < 1) { qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << "No channels found, aborting setup."; - return false; + if (retryConnectCount < 10) { + QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); + retryConnectCount++; + return false; + } } aParams.nChannels = outFormat.channelCount(); From 50eb498026763907f2e3294b86badf576925e08a Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 10:30:26 +0100 Subject: [PATCH 08/23] Another error check --- rthandler.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rthandler.cpp b/rthandler.cpp index a392c46..5b542c5 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -92,6 +92,10 @@ bool rtHandler::init(audioSetup setup) } catch (RtAudioError& e) { qInfo(logAudio()) << "Device error:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage()); + if (retryConnectCount < 10) { + QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); + retryConnectCount++; + } return isInitialized; } From b95cf793186f988d6e19b71900a6fe5e4beab98e Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 10:33:31 +0100 Subject: [PATCH 09/23] Update rthandler.cpp --- rthandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rthandler.cpp b/rthandler.cpp index 5b542c5..44f343c 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -91,7 +91,7 @@ bool rtHandler::init(audioSetup setup) info = audio->getDeviceInfo(aParams.deviceId); } catch (RtAudioError& e) { - qInfo(logAudio()) << "Device error:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage()); + qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Device exception:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage()); if (retryConnectCount < 10) { QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); retryConnectCount++; From 466571a7584705872bbd4decc7ea5b5c4e7b247c Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 10:41:44 +0100 Subject: [PATCH 10/23] Use goto statement for error handling. --- rthandler.cpp | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/rthandler.cpp b/rthandler.cpp index 44f343c..c3d0353 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -92,11 +92,7 @@ bool rtHandler::init(audioSetup setup) } catch (RtAudioError& e) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Device exception:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage()); - if (retryConnectCount < 10) { - QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); - retryConnectCount++; - } - return isInitialized; + goto errorHandler; } if (info.probed) @@ -110,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:" << @@ -137,11 +133,7 @@ bool rtHandler::init(audioSetup setup) else if (outFormat.channelCount() < 1) { qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << "No channels found, aborting setup."; - if (retryConnectCount < 10) { - QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); - retryConnectCount++; - return false; - } + goto errorHandler; } aParams.nChannels = outFormat.channelCount(); @@ -170,7 +162,7 @@ bool rtHandler::init(audioSetup setup) } else { qCritical(logAudio()) << "Cannot find supported sample format!"; - return false; + goto errorHandler; } } @@ -217,27 +209,32 @@ bool rtHandler::init(audioSetup setup) catch (RtAudioError& e) { qInfo(logAudio()) << "Error opening:" << QString::fromStdString(e.getMessage()); // Try again? - if (retryConnectCount < 10) { - QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); - retryConnectCount++; - return false; - } + goto errorHandler; } } else { - qCritical(logAudio()) << (setup.isinput ? "Input" : "Output") << QString::fromStdString(info.name) << "(" << aParams.deviceId << ") could not be probed, check audio configuration!"; - if (retryConnectCount < 10) { - QTimer::singleShot(500, this, std::bind(&rtHandler::init, this, setup)); - retryConnectCount++; - return false; - } + 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; + } From e248882e31c627240e6925da1f2ad6a86aa57282 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:07:05 +0100 Subject: [PATCH 11/23] Add reconnect on failure to commHandler() --- commhandler.cpp | 15 ++++++++++++++- commhandler.h | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/commhandler.cpp b/commhandler.cpp index be6fb5b..a8ac59e 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -29,6 +29,7 @@ commHandler::commHandler(QObject* parent) : QObject(parent) //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))); } commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QObject* parent) : QObject(parent) @@ -143,7 +144,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()\ @@ -371,3 +372,15 @@ void commHandler::printHex(const QByteArray &pdata, bool printVert, bool printHo } +void commHandler::handleError(QSerialPort::SerialPortError err) +{ + switch (err) { + case QSerialPort::NoError: + break; + default: + qDebug(logSerial()) << "Serial port" << port->portName() << "Error, attempting disconnect/reconnect"; + closePort(); + openPort(); + break; + } +} diff --git a/commhandler.h b/commhandler.h index 5546175..d23673b 100644 --- a/commhandler.h +++ b/commhandler.h @@ -25,6 +25,7 @@ public: public slots: void setUseRTSforPTT(bool useRTS); void setRTS(bool rtsOn); + void handleError(QSerialPort::SerialPortError error); private slots: void receiveDataIn(); // from physical port From 630d2eaba3ba7a6d3e629dca0878ec2ed3727a5f Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:10:27 +0100 Subject: [PATCH 12/23] Update commhandler.cpp --- commhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commhandler.cpp b/commhandler.cpp index a8ac59e..a771fad 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -90,7 +90,7 @@ void commHandler::sendDataOut(const QByteArray &writeData) { mutex.lock(); // Recycle port to attempt reconnection. - if (!this->isConnected) { + if (!this->isConnected || !port->isOpen()) { closePort(); openPort(); } From f003a8a1b877e80eaf4f63ce1dcdb74c8ae89927 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:13:20 +0100 Subject: [PATCH 13/23] Update commhandler.cpp --- commhandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/commhandler.cpp b/commhandler.cpp index a771fad..0c8eeeb 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -96,6 +96,7 @@ void commHandler::sendDataOut(const QByteArray &writeData) } if (!this->isConnected) { + mutex.unlock(); return; } qint64 bytesWritten; From 6078a31a3c4b78262806f44546d6c8f4499f2f7c Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:24:09 +0100 Subject: [PATCH 14/23] Add timeout if no data received on serial port for 2s --- commhandler.cpp | 5 ++++- commhandler.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/commhandler.cpp b/commhandler.cpp index 0c8eeeb..800fe4e 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -30,6 +30,7 @@ commHandler::commHandler(QObject* parent) : QObject(parent) connect(port, SIGNAL(readyRead()), this, SLOT(receiveDataIn())); connect(port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError))); + lastDataReceived = QTime::currentTime(); } commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QObject* parent) : QObject(parent) @@ -90,7 +91,8 @@ void commHandler::sendDataOut(const QByteArray &writeData) { mutex.lock(); // Recycle port to attempt reconnection. - if (!this->isConnected || !port->isOpen()) { + if (!this->isConnected || !port->isOpen() || lastDataReceived.msecsTo(QTime::currentTime()) > 2000) { + qDebug(logSerial()) << "Serial port error? Attempting reconnect..."; closePort(); openPort(); } @@ -164,6 +166,7 @@ void commHandler::receiveDataIn() // because we know what constitutes a valid "frame" of data. // new code: + lastDataReceived = QTime::currentTime(); port->startTransaction(); inPortData = port->readAll(); diff --git a/commhandler.h b/commhandler.h index d23673b..38c2d5c 100644 --- a/commhandler.h +++ b/commhandler.h @@ -6,6 +6,7 @@ #include #include #include +#include // This class abstracts the comm port in a useful way and connects to // the command creator and command parser. @@ -83,6 +84,7 @@ private: quint8 spectrumInformation; quint8 spectrumOutOfRange; quint8 lastSpectrum = 0; + QTime lastDataReceived; }; #endif // COMMHANDLER_H From b049704dd2cdcbaf78ec3ed897fd8635aee804a5 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:35:41 +0100 Subject: [PATCH 15/23] Use qtimer to signal a reconnect --- commhandler.cpp | 30 +++++++++++++++++++----------- commhandler.h | 4 +++- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/commhandler.cpp b/commhandler.cpp index 800fe4e..5e592f0 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -40,7 +40,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; @@ -55,6 +54,17 @@ commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QO this->portName = portName; this->PTTviaRTS = false; +} + +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(); @@ -62,9 +72,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(); @@ -89,18 +100,16 @@ void commHandler::receiveDataFromUserToRig(const QByteArray &data) void commHandler::sendDataOut(const QByteArray &writeData) { - mutex.lock(); // Recycle port to attempt reconnection. if (!this->isConnected || !port->isOpen() || lastDataReceived.msecsTo(QTime::currentTime()) > 2000) { qDebug(logSerial()) << "Serial port error? Attempting reconnect..."; - closePort(); - openPort(); - } - - if (!this->isConnected) { - mutex.unlock(); + lastDataReceived = QTime::currentTime(); + QTimer::singleShot(500, this, SLOT(init())); return; } + + mutex.lock(); + qint64 bytesWritten; if(PTTviaRTS) @@ -383,8 +392,7 @@ void commHandler::handleError(QSerialPort::SerialPortError err) break; default: qDebug(logSerial()) << "Serial port" << port->portName() << "Error, attempting disconnect/reconnect"; - closePort(); - openPort(); + QTimer::singleShot(500, this, SLOT(init())); break; } } diff --git a/commhandler.h b/commhandler.h index 38c2d5c..acfc8be 100644 --- a/commhandler.h +++ b/commhandler.h @@ -7,6 +7,7 @@ #include #include #include +#include // This class abstracts the comm port in a useful way and connects to // the command creator and command parser. @@ -27,6 +28,7 @@ public slots: void setUseRTSforPTT(bool useRTS); void setRTS(bool rtsOn); void handleError(QSerialPort::SerialPortError error); + void init(); private slots: void receiveDataIn(); // from physical port @@ -60,7 +62,7 @@ private: unsigned char buffer[256]; QString portName; - QSerialPort *port; + QSerialPort *port=Q_NULLPTR; qint32 baudrate; unsigned char stopbits; bool rolledBack; From 1305f06eabe8886c37cf319edc7eb87435a7c7ad Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:38:35 +0100 Subject: [PATCH 16/23] Update commhandler.cpp --- commhandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/commhandler.cpp b/commhandler.cpp index 5e592f0..437d88d 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -53,6 +53,7 @@ commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QO stopbits = 1; this->portName = portName; this->PTTviaRTS = false; + init(); } From d468e01d20beaa830f7a3bc289da7cf41e739675 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:39:52 +0100 Subject: [PATCH 17/23] Update commhandler.cpp --- commhandler.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/commhandler.cpp b/commhandler.cpp index 437d88d..2716335 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -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,15 +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())); - connect(port, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError))); - lastDataReceived = QTime::currentTime(); + init(); } commHandler::commHandler(QString portName, quint32 baudRate, quint8 wfFormat, QObject* parent) : QObject(parent) From 2e1d88c19490195aa1273da4ed381901d589e7b3 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:40:58 +0100 Subject: [PATCH 18/23] Update commhandler.cpp --- commhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commhandler.cpp b/commhandler.cpp index 2716335..bee481a 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -88,7 +88,7 @@ void commHandler::receiveDataFromUserToRig(const QByteArray &data) void commHandler::sendDataOut(const QByteArray &writeData) { // Recycle port to attempt reconnection. - if (!this->isConnected || !port->isOpen() || lastDataReceived.msecsTo(QTime::currentTime()) > 2000) { + if (!this->isConnected || lastDataReceived.msecsTo(QTime::currentTime()) > 2000) { qDebug(logSerial()) << "Serial port error? Attempting reconnect..."; lastDataReceived = QTime::currentTime(); QTimer::singleShot(500, this, SLOT(init())); From bcde69c92b3f1b7f7ce21a11e802837694f5b308 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 11:48:58 +0100 Subject: [PATCH 19/23] Update commhandler.cpp --- commhandler.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/commhandler.cpp b/commhandler.cpp index bee481a..3b500ef 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -88,7 +88,7 @@ void commHandler::receiveDataFromUserToRig(const QByteArray &data) void commHandler::sendDataOut(const QByteArray &writeData) { // Recycle port to attempt reconnection. - if (!this->isConnected || lastDataReceived.msecsTo(QTime::currentTime()) > 2000) { + if (lastDataReceived.msecsTo(QTime::currentTime()) > 2000) { qDebug(logSerial()) << "Serial port error? Attempting reconnect..."; lastDataReceived = QTime::currentTime(); QTimer::singleShot(500, this, SLOT(init())); @@ -378,8 +378,11 @@ void commHandler::handleError(QSerialPort::SerialPortError err) case QSerialPort::NoError: break; default: - qDebug(logSerial()) << "Serial port" << port->portName() << "Error, attempting disconnect/reconnect"; - QTimer::singleShot(500, this, SLOT(init())); + 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; } } From b3f611543c23679a593e9bffb5bf5e51c6205cd1 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 13:45:56 +0100 Subject: [PATCH 20/23] Make RT/PA a subclass of audioHandler --- pahandler.h | 3 ++- rthandler.h | 4 ++-- udpaudio.h | 4 ++-- udpserver.cpp | 8 ++++---- udpserver.h | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pahandler.h b/pahandler.h index cd55e95..a8fac05 100644 --- a/pahandler.h +++ b/pahandler.h @@ -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 -class paHandler : public QObject +class paHandler : public audioHandler { Q_OBJECT diff --git a/rthandler.h b/rthandler.h index 10acd78..cbbd4b4 100644 --- a/rthandler.h +++ b/rthandler.h @@ -25,14 +25,14 @@ /* Logarithmic taper for volume control */ #include "audiotaper.h" - +#include "audiohandler.h" /* Audio converter class*/ #include "audioconverter.h" #include -class rtHandler : public QObject +class rtHandler : public audioHandler { Q_OBJECT diff --git a/udpaudio.h b/udpaudio.h index 478c342..87ae9cf 100644 --- a/udpaudio.h +++ b/udpaudio.h @@ -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; diff --git a/udpserver.cpp b/udpserver.cpp index 255ba61..b99f2eb 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -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); diff --git a/udpserver.h b/udpserver.h index ff2e78d..3cbed99 100644 --- a/udpserver.h +++ b/udpserver.h @@ -70,9 +70,9 @@ 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; From 8f5ba2efb197f2f6edfca3834559b8cf5980b966 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 13:54:09 +0100 Subject: [PATCH 21/23] Convert audioHandler functions to virtual --- audiohandler.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/audiohandler.h b/audiohandler.h index 9c503ec..a793973 100644 --- a/audiohandler.h +++ b/audiohandler.h @@ -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); From 5ef50c97069aa71f5a40fe2e3891b81126c1e394 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 14:02:31 +0100 Subject: [PATCH 22/23] Update rthandler.cpp --- rthandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rthandler.cpp b/rthandler.cpp index c3d0353..96229f2 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -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) { From 079a50980d91b1792699885ed44387e8aca65d08 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sat, 14 May 2022 15:05:48 +0100 Subject: [PATCH 23/23] Fix RT/PA builds on MacOs --- rthandler.cpp | 4 ++-- rthandler.h | 2 +- wfmain.h | 4 ++-- wfserver.pro | 4 ++-- wfview.pro | 5 +++-- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/rthandler.cpp b/rthandler.cpp index 96229f2..b7438f5 100644 --- a/rthandler.cpp +++ b/rthandler.cpp @@ -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; @@ -90,7 +90,7 @@ bool rtHandler::init(audioSetup setup) try { info = audio->getDeviceInfo(aParams.deviceId); } - catch (RtAudioError& e) { + catch (RtAudioError e) { qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "Device exception:" << aParams.deviceId << ":" << QString::fromStdString(e.getMessage()); goto errorHandler; } diff --git a/rthandler.h b/rthandler.h index cbbd4b4..c48a2b4 100644 --- a/rthandler.h +++ b/rthandler.h @@ -6,7 +6,7 @@ #include #include -#ifdef Q_OS_WIN +#ifndef Q_OS_LINUX #include "RtAudio.h" #else #include "rtaudio/RtAudio.h" diff --git a/wfmain.h b/wfmain.h index 29bded4..e691258 100644 --- a/wfmain.h +++ b/wfmain.h @@ -41,7 +41,7 @@ #include #include -#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 \ No newline at end of file +#endif diff --git a/wfserver.pro b/wfserver.pro index d17f9eb..bbd4fee 100644 --- a/wfserver.pro +++ b/wfserver.pro @@ -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 diff --git a/wfview.pro b/wfview.pro index ef0e2be..63d0391 100644 --- a/wfview.pro +++ b/wfview.pro @@ -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