diff --git a/audiohandler.cpp b/audiohandler.cpp index 6ba6300..0351ece 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -979,7 +979,7 @@ qint64 audioHandler::readData(char* data, qint64 maxlen) if (timediff > (int)latency * 2) { qDebug(logAudio()) << "Packet " << hex << packet->seq << - " arrived too late (increase rx latency!) " << + " arrived too late (increase output latency!) " << dec << packet->time.msecsTo(QTime::currentTime()) << "ms"; while (packet !=audioBuffer.end() && timediff > (int)latency) { timediff = packet->time.msecsTo(QTime::currentTime()); @@ -1060,7 +1060,7 @@ qint64 audioHandler::writeData(const char* data, qint64 len) { chunkAvailable = true; } - else if (audioBuffer.length()==1 && current->sent != chunkSize) { + else if (audioBuffer.length()<=1 && current->sent != chunkSize) { chunkAvailable = false; } @@ -1094,7 +1094,7 @@ void audioHandler::stateChanged(QAudio::State state) qDebug(logAudio()) << "Audio now in idle state: " << audioBuffer.length() << " packets in buffer, isInput=" << isInput; if (audioOutput != Q_NULLPTR && audioOutput->error() == QAudio::UnderrunError) { - qDebug(logAudio()) << this->metaObject()->className() << "RX:Buffer underrun, isInput=" << isInput; + qDebug(logAudio()) << this->metaObject()->className() << "Output buffer underrun, isInput=" << isInput; audioOutput->suspend(); } break; @@ -1187,7 +1187,7 @@ void audioHandler::incomingAudio(audioPacket data) // Restart playback if (audioOutput->state() == QAudio::SuspendedState) { - qDebug(logAudio()) << "RX Audio Suspended, Resuming..."; + qDebug(logAudio()) << "Output Audio Suspended, Resuming..."; audioOutput->resume(); } } diff --git a/commhandler.cpp b/commhandler.cpp index 8021c0d..4e1e48b 100644 --- a/commhandler.cpp +++ b/commhandler.cpp @@ -76,22 +76,15 @@ void commHandler::receiveDataFromUserToRig(const QByteArray &data) void commHandler::sendDataOut(const QByteArray &writeData) { - mutex.lock(); -#ifdef QT_DEBUG - qint64 bytesWritten; - bytesWritten = port->write(writeData); - qDebug(logSerial()) << "bytesWritten: " << bytesWritten << " length of byte array: " << writeData.length()\ - << " size of byte array: " << writeData.size()\ - << " Wrote all bytes? " << (bool) (bytesWritten == (qint64)writeData.size()); - -#else - port->write(writeData); - -#endif + if (bytesWritten != writeData.length()) { + qDebug(logSerial()) << "bytesWritten: " << bytesWritten << " length of byte array: " << writeData.length()\ + << " size of byte array: " << writeData.size()\ + << " Wrote all bytes? " << (bool)(bytesWritten == (qint64)writeData.size()); + } mutex.unlock(); } diff --git a/packettypes.h b/packettypes.h index 17e270b..46cad4c 100644 --- a/packettypes.h +++ b/packettypes.h @@ -147,17 +147,21 @@ typedef union token_packet { quint16 seq; // 0x06 quint32 sentid; // 0x08 quint32 rcvdid; // 0x0c - char unuseda[3]; // 0x10 + char unuseda[3]; // 0x10 quint16 code; // 0x13 quint16 res; // 0x15 - quint8 innerseq; // 0x17 - char unusedb; // 0x18 - char unusedc; // 0x19 + quint8 innerseq; // 0x17 + char unusedb; // 0x18 + char unusedc; // 0x19 quint16 tokrequest; // 0x1a quint32 token; // 0x1c - char unusedd[16]; // 0x20 + char unusedd[7]; // 0x20 + quint16 commoncap; // 0x27 + char unuseddd[2]; // 0x29 + char identa; // 0x2b + quint32 identb; // 0x2c quint32 response; // 0x30 - char unusede[12]; // 0x34 + char unusede[12]; // 0x34 }; char packet[TOKEN_SIZE]; } *token_packet_t; diff --git a/udphandler.cpp b/udphandler.cpp index a4d8665..ef5d20d 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -783,7 +783,7 @@ void udpAudio::sendTxAudio() txaudio->getNextAudioChunk(audio); int counter = 1; int len = 0; - + while (len < audio.length()) { QByteArray partial = audio.mid(len, 1364); audio_packet p; diff --git a/udphandler.h b/udphandler.h index 9bc6738..b55faa6 100644 --- a/udphandler.h +++ b/udphandler.h @@ -129,7 +129,7 @@ public: quint32 packetsSent=0; quint32 packetsLost=0; - quint16 seqPrefix=0; + quint16 seqPrefix = 0; private: void sendRetransmitRequest(); @@ -173,10 +173,10 @@ public: ~udpAudio(); signals: - void haveAudioData(audioPacket data); + void haveAudioData(audioPacket data); - void setupTxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput, QString port,quint8 resampleQuality); - void setupRxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput, QString port,quint8 resampleQuality); + void setupTxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput, QString port, quint8 resampleQuality); + void setupRxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput, QString port, quint8 resampleQuality); void haveChangeLatency(quint16 value); @@ -206,11 +206,11 @@ private: bool sentPacketConnect2 = false; uint16_t sendAudioSeq = 0; - audioHandler* rxaudio=Q_NULLPTR; - QThread* rxAudioThread=Q_NULLPTR; + audioHandler* rxaudio = Q_NULLPTR; + QThread* rxAudioThread = Q_NULLPTR; - audioHandler* txaudio=Q_NULLPTR; - QThread* txAudioThread=Q_NULLPTR; + audioHandler* txaudio = Q_NULLPTR; + QThread* txAudioThread = Q_NULLPTR; QTimer* txAudioTimer=Q_NULLPTR; diff --git a/udpserver.cpp b/udpserver.cpp index 7b65f2f..8b10c13 100644 --- a/udpserver.cpp +++ b/udpserver.cpp @@ -56,6 +56,7 @@ void udpServer::init() udpAudio = new QUdpSocket(this); udpAudio->bind(config.audioPort); QUdpSocket::connect(udpAudio, &QUdpSocket::readyRead, this, &udpServer::audioReceived); + } udpServer::~udpServer() @@ -124,7 +125,21 @@ udpServer::~udpServer() audioClients.removeAll(client); } + if (rxAudioTimer != Q_NULLPTR) { + rxAudioTimer->stop(); + delete rxAudioTimer; + rxAudioTimer = Q_NULLPTR; + } + if (rxAudioThread != Q_NULLPTR) { + rxAudioThread->quit(); + rxAudioThread->wait(); + } + + if (txAudioThread != Q_NULLPTR) { + txAudioThread->quit(); + txAudioThread->wait(); + } if (udpControl != Q_NULLPTR) { udpControl->close(); @@ -138,7 +153,6 @@ udpServer::~udpServer() udpAudio->close(); delete udpAudio; } - } @@ -257,6 +271,8 @@ void udpServer::controlReceived() token_packet_t in = (token_packet_t)r.constData(); current->rxSeq = in->seq; current->authInnerSeq = in->innerseq; + current->identa = in->identa; + current->identb = in->identb; if (in->res == 0x02) { // Request for new token qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received create token request"; @@ -268,6 +284,12 @@ void udpServer::controlReceived() qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received token disconnect request"; sendTokenResponse(current, in->res); } + else if (in->res == 0x04) { + // Disconnect audio/civ + sendTokenResponse(current, in->res); + current->isStreaming = false; + sendConnectionInfo(current); + } else { qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received token request"; sendTokenResponse(current, in->res); @@ -321,14 +343,92 @@ void udpServer::controlReceived() current->rxSeq = in->seq; current->rxCodec = in->rxcodec; current->txCodec = in->txcodec; - current->rxSampleRate = qFromBigEndian(in->rxsample); - current->txSampleRate = qFromBigEndian(in->txsample); - current->txBufferLen = qFromBigEndian(in->txbuffer); + current->rxSampleRate = qFromBigEndian(in->rxsample); + current->txSampleRate = qFromBigEndian(in->txsample); + current->txBufferLen = qFromBigEndian(in->txbuffer); current->authInnerSeq = in->innerseq; - current->ident = in->identb; + current->identa = in->identa; + current->identb = in->identb; sendStatus(current); current->authInnerSeq = 0x00; sendConnectionInfo(current); + qDebug(logUdpServer()) << "rxCodec:" << current->rxCodec << " txCodec:" << current->txCodec << + " rxSampleRate" << current->rxSampleRate << + " txSampleRate" << current->rxSampleRate << + " txBufferLen" << current->txBufferLen; + + if (!config.lan) { + // Radio is connected by USB/Serial and we assume that audio is connected as well. + // Create audio TX/RX threads if they don't already exist (first client chooses samplerate/codec) + if (txaudio == Q_NULLPTR) + { + bool uLaw = false; + quint8 channels = 1; + quint8 samples = 8; + txSampleRate = current->txSampleRate; + txCodec = current->txCodec; + + if (current->txCodec == 0x01 || current->txCodec == 0x20) { + uLaw = true; + } + if (current->txCodec == 0x08 || current->txCodec == 0x10 || current->txCodec == 0x20) { + channels = 2; + } + if (current->txCodec == 0x04 || current->txCodec == 0x10) { + samples = 16; + } + + + txaudio = new audioHandler(); + txAudioThread = new QThread(this); + txaudio->moveToThread(txAudioThread); + + txAudioThread->start(); + + connect(this, SIGNAL(setupTxAudio(quint8, quint8, quint16, quint16, bool, bool, QString, quint8)), txaudio, SLOT(init(quint8, quint8, quint16, quint16, bool, bool, QString, quint8))); + connect(txAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater())); + + emit setupTxAudio(samples, channels, current->txSampleRate, in->txbuffer, uLaw, false, config.audioOutput, config.resampleQuality); + hasTxAudio=datagram.senderAddress(); + + connect(this, SIGNAL(haveAudioData(audioPacket)), txaudio, SLOT(incomingAudio(audioPacket))); + + } + if (rxaudio == Q_NULLPTR) + { + bool uLaw = false; + quint8 channels = 1; + quint8 samples = 8; + rxSampleRate = current->rxSampleRate; + rxCodec = current->rxCodec; + + if (current->rxCodec == 0x01 || current->rxCodec == 0x20) { + uLaw = true; + } + if (current->rxCodec == 0x08 || current->rxCodec == 0x10 || current->rxCodec == 0x20) { + channels = 2; + } + if (current->rxCodec == 0x04 || current->rxCodec == 0x10) { + samples = 16; + } + + + rxaudio = new audioHandler(); + rxAudioThread = new QThread(this); + rxaudio->moveToThread(rxAudioThread); + rxAudioThread->start(); + + connect(this, SIGNAL(setupRxAudio(quint8, quint8, quint16, quint16, bool, bool, QString, quint8)), rxaudio, SLOT(init(quint8, quint8, quint16, quint16, bool, bool, QString, quint8))); + connect(rxAudioThread, SIGNAL(finished()), txaudio, SLOT(deleteLater())); + + emit setupRxAudio(samples, channels, current->rxSampleRate, 150, uLaw, true, config.audioInput, config.resampleQuality); + + rxAudioTimer = new QTimer(); + connect(rxAudioTimer, &QTimer::timeout, this, std::bind(&udpServer::sendRxAudio, this)); + rxAudioTimer->start(10); + } + + } break; } @@ -497,7 +597,7 @@ void udpServer::audioReceived() current->retransmitTimer = new QTimer(); connect(current->retransmitTimer, &QTimer::timeout, this, std::bind(&udpServer::sendRetransmitRequest, this, current)); current->retransmitTimer->start(RETRANSMIT_PERIOD); - + current->seqPrefix = 0; qDebug(logUdpServer()) << "New Audio connection created from :" << current->ipAddress.toString() << ":" << QString::number(current->port); audioClients.append(current); } @@ -531,11 +631,42 @@ void udpServer::audioReceived() } break; } - default: { + /* Audio packets start as follows: + PCM 16bit and PCM8/uLAW stereo: 0x44,0x02 for first packet and 0x6c,0x05 for second. + uLAW 8bit/PCM 8bit 0xd8,0x03 for all packets + PCM 16bit stereo 0x6c,0x05 first & second 0x70,0x04 third + + + */ + control_packet_t in = (control_packet_t)r.constData(); + + if (in->type != 0x01 && in->len >= 0xAC) { + if (in->seq == 0) + { + // Seq number has rolled over. + current->seqPrefix++; + } + + // 0xac is the smallest possible audio packet. + audioPacket tempAudio; + tempAudio.seq = (quint32)current->seqPrefix << 16 | in->seq; + tempAudio.time = QTime::currentTime();; + tempAudio.sent = 0; + tempAudio.datain = r.mid(0x18); + // Prefer signal/slot to forward audio as it is thread/safe + // Need to do more testing but latency appears fine. + //if (hasTxAudio == datagram.senderAddress()) + //{ + qDebug(logUdpServer()) << "sending tx audio " << in->seq; + emit haveAudioData(tempAudio); + //} + //rxaudio->incomingAudio(tempAudio); + } break; } + } commonReceived(&audioClients, current, r); @@ -563,13 +694,13 @@ void udpServer::commonReceived(QList* l,CLIENT* current, QByteArray r) if (in->type == 0x03) { qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received 'are you there'"; current->remoteId = in->sentid; - sendControl(current, 0x04, 0x00); + sendControl(current, 0x04, in->seq); } // This is This is "Are you ready" in response to "I am here". else if (in->type == 0x06) { qDebug(logUdpServer()) << current->ipAddress.toString() << ": Received 'Are you ready'"; current->remoteId = in->sentid; - sendControl(current, 0x06, 0x00); + sendControl(current, 0x06, in->seq); } // This is a retransmit request else if (in->type == 0x01) { @@ -801,7 +932,7 @@ void udpServer::sendCapabilities(CLIENT* c) p.seq = c->txSeq; p.sentid = c->myId; p.rcvdid = c->remoteId; - p.innerseq = c->authInnerSeq; + p.innerseq = c->authInnerSeq; p.tokrequest = c->tokenRx; p.token = c->tokenTx; p.code = 0x0298; @@ -809,26 +940,23 @@ void udpServer::sendCapabilities(CLIENT* c) p.capa = 0x01; p.commoncap = c->commonCap; - memcpy(p.macaddress, macAddress.toLocal8Bit(), 6); + memcpy(p.macaddress, macAddress.toLocal8Bit(), 6); // IRU seems to expect an "Icom" mac address so replace the first 3 octets of our Mac with one in their range! memcpy(p.macaddress, QByteArrayLiteral("\x00\x90\xc7").constData(), 3); - memcpy(p.name, rigCaps.modelName.toLocal8Bit(), rigname.length()); + memcpy(p.name, rigCaps.modelName.toLocal8Bit(), rigCaps.modelName.length()); memcpy(p.audio, QByteArrayLiteral("ICOM_VAUDIO").constData(), 11); if (rigCaps.hasWiFi && !rigCaps.hasEthernet) { p.conntype = 0x0707; // 0x0707 for wifi rig. } else { - p.conntype = 0x073f; // 0x0707 for ethernet rig. + p.conntype = 0x073f; // 0x073f for ethernet rig. } p.civ = rigCaps.civ; p.baudrate = (quint32)qToBigEndian(19200); - - //p.lena = 0x8b01; // rx sample frequencies supported - //p.lenb = 0x8b01; // tx sample frequencies supported /* 0x80 = 12K only 0x40 = 44.1K only @@ -839,11 +967,52 @@ void udpServer::sendCapabilities(CLIENT* c) 0x02 = 16K only 0x01 = 8K only */ - p.rxsample = 0x0800; // rx sample frequency - p.txsample = 0x0800; // tx sample frequency + if (rxaudio == Q_NULLPTR) { + p.rxsample = 0x8b01; // all rx sample frequencies supported + } + else { + if (rxSampleRate == 48000) { + p.rxsample = 0x0800; // fixed rx sample frequency + } + else if (rxSampleRate == 32000) { + p.rxsample = 0x0400; + } + else if (rxSampleRate == 24000) { + p.rxsample = 0x0001; + } + else if (rxSampleRate == 16000) { + p.rxsample = 0x0200; + } + else if (rxSampleRate == 12000) { + p.rxsample = 0x8000; + } + } + + if (txaudio == Q_NULLPTR) { + p.txsample = 0x8b01; // all tx sample frequencies supported + p.enablea = 0x01; // 0x01 enables TX 24K mode? + } + else { + p.enablea = 0x00; // 0x01 enables TX 24K mode? + if (txSampleRate == 48000) { + p.txsample = 0x0800; // fixed tx sample frequency + } + else if (txSampleRate == 32000) { + p.txsample = 0x0400; + } + else if (txSampleRate == 24000) { + p.txsample = 0x0000; + p.enablea = 0x01; + } + else if (txSampleRate == 16000) { + p.txsample = 0x0200; + } + else if (txSampleRate == 12000) { + p.txsample = 0x8000; + } + } // I still don't know what these are? - p.enablea = 0x00; // 0x01 enables TX 24K mode? p.enableb = 0x01; // 0x01 doesn't seem to do anything? p.enablec = 0x01; // 0x01 doesn't seem to do anything? p.capf = 0x5001; @@ -882,20 +1051,21 @@ void udpServer::sendConnectionInfo(CLIENT* c) p.token = c->tokenTx; p.code = 0x0380; p.commoncap = c->commonCap; - p.identa = (char)0x90; - p.identb = c->ident; + p.identa = c->identa; + p.identb = c->identb; // 0x1a-0x1f is authid (random number? // memcpy(p + 0x40, QByteArrayLiteral("IC-7851").constData(), 7); - memcpy(p.packet + 0x40, rigname.toLocal8Bit(), rigname.length()); + memcpy(p.packet + 0x40, rigCaps.modelName.toLocal8Bit(), rigCaps.modelName.length()); // This is the current streaming client (should we support multiple clients?) if (c->isStreaming) { p.busy = 0x01; memcpy(p.computer, c->clientName.constData(), c->clientName.length()); p.ipaddress = qToBigEndian(c->ipAddress.toIPv4Address()); - p.identb = c->ident; + p.identa = c->identa; + p.identb = c->identb; } QMutexLocker locker(&mutex); @@ -929,6 +1099,9 @@ void udpServer::sendTokenResponse(CLIENT* c, quint8 type) p.tokrequest = c->tokenRx; p.token = c->tokenTx; p.code = 0x0230; + p.identa = c->identa; + p.identb = c->identb; + p.commoncap = c->commonCap; p.res = type; QMutexLocker locker(&mutex); @@ -996,8 +1169,8 @@ void udpServer::sendStatus(CLIENT* c) p.res = 0x03; p.unknown = 0x1000; p.unusede = (char)0x80; - p.identa = (char)0x90; - p.identb = c->ident; + p.identa = c->identa; + p.identb = c->identb; p.civport=qToBigEndian(c->civPort); p.audioport=qToBigEndian(c->audioPort); @@ -1054,6 +1227,24 @@ void udpServer::dataForServer(QByteArray d) return; } +void udpServer::sendRxAudio() +{ + if (rxaudio && rxaudio->isChunkAvailable()) { + QByteArray audio; + rxaudio->getNextAudioChunk(audio); + int len = 0; + + while (len < audio.length()) { + audioPacket partial; + partial.datain = audio.mid(len, 1364); + receiveAudioData(partial); + len = len + partial.datain.length(); + } + } +} + + + void udpServer::receiveAudioData(const audioPacket &d) { //qDebug(logUdpServer()) << "Server got:" << d.data.length(); @@ -1068,6 +1259,7 @@ void udpServer::receiveAudioData(const audioPacket &d) p.ident = 0x0080; // audio is always this? p.datalen = (quint16)qToBigEndian((quint16)d.datain.length()); p.sendseq = (quint16)qToBigEndian((quint16)client->sendAudioSeq); // THIS IS BIG ENDIAN! + p.seq = client->txSeq; QByteArray t = QByteArray::fromRawData((const char*)p.packet, sizeof(p)); t.append(d.datain); QMutexLocker locker(&mutex); @@ -1216,4 +1408,28 @@ void udpServer::deleteConnection(QList *l, CLIENT* c) delete c; // Is this needed or will the erase have done it? c = Q_NULLPTR; qDebug(logUdpServer()) << "Current Number of clients connected: " << l->length(); + + if (l->length() == 0) { + + if (rxAudioTimer != Q_NULLPTR) { + rxAudioTimer->stop(); + delete rxAudioTimer; + rxAudioTimer = Q_NULLPTR; + } + + if (rxAudioThread != Q_NULLPTR) { + rxAudioThread->quit(); + rxAudioThread->wait(); + rxaudio = Q_NULLPTR; + rxAudioThread = Q_NULLPTR; + } + + if (txAudioThread != Q_NULLPTR) { + txAudioThread->quit(); + txAudioThread->wait(); + txaudio = Q_NULLPTR; + txAudioThread = Q_NULLPTR; + } + + } } diff --git a/udpserver.h b/udpserver.h index 38ba5d5..cca3b62 100644 --- a/udpserver.h +++ b/udpserver.h @@ -49,6 +49,10 @@ public slots: signals: void haveDataFromServer(QByteArray); + void haveAudioData(audioPacket data); + void setupTxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput, QString port, quint8 resampleQuality); + void setupRxAudio(const quint8 samples, const quint8 channels, const quint16 samplerate, const quint16 latency, const bool isUlaw, const bool isInput, QString port, quint8 resampleQuality); + private: @@ -74,7 +78,8 @@ private: quint16 authSeq; quint16 innerSeq; quint16 sendAudioSeq; - quint32 ident; + quint8 identa; + quint32 identb; quint16 tokenRx; quint32 tokenTx; quint32 commonCap; @@ -97,7 +102,7 @@ private: QVector txSeqBuf; QVector rxSeqBuf; QVector rxMissing; - + quint16 seqPrefix; }; void controlReceived(); @@ -114,6 +119,7 @@ private: void sendStatus(CLIENT* c); void sendRetransmitRequest(CLIENT* c); void watchdog(CLIENT* c); + void sendRxAudio(); void deleteConnection(QList *l, CLIENT* c); SERVERCONFIG config; @@ -128,7 +134,6 @@ private: quint32 civId = 0; quint32 audioId = 0; - QString rigname = "IC-9700"; quint8 rigciv = 0xa2; QMutex mutex; // Used for critical operations. @@ -138,6 +143,20 @@ private: QList audioClients = QList(); QTime timeStarted; rigCapabilities rigCaps; + + audioHandler* rxaudio = Q_NULLPTR; + QThread* rxAudioThread = Q_NULLPTR; + + audioHandler* txaudio = Q_NULLPTR; + QThread* txAudioThread = Q_NULLPTR; + + QTimer* rxAudioTimer=Q_NULLPTR; + quint16 rxSampleRate = 0; + quint16 txSampleRate = 0; + quint8 rxCodec = 0; + quint8 txCodec = 0; + + QHostAddress hasTxAudio; }; diff --git a/udpserversetup.h b/udpserversetup.h index bc7396e..b707401 100644 --- a/udpserversetup.h +++ b/udpserversetup.h @@ -16,9 +16,14 @@ struct SERVERUSER { struct SERVERCONFIG { bool enabled; + bool lan; quint16 controlPort; quint16 civPort; quint16 audioPort; + QString audioOutput; + QString audioInput; + quint8 resampleQuality; + QList users; }; diff --git a/wfmain.cpp b/wfmain.cpp index 7169e07..7dc402a 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -201,6 +201,12 @@ wfmain::wfmain(const QString serialPortCL, const QString hostCL, QWidget *parent // Start server if enabled in config if (serverConfig.enabled) { + serverConfig.lan = prefs.enableLAN; + if (!serverConfig.lan) { + serverConfig.resampleQuality = udpPrefs.resampleQuality; + serverConfig.audioInput = udpPrefs.audioInput; + serverConfig.audioOutput = udpPrefs.audioOutput; + } udp = new udpServer(serverConfig); serverThread = new QThread(this); @@ -863,7 +869,7 @@ void wfmain::loadSettings() udpPrefs.audioOutput = settings.value("AudioOutput", udpDefPrefs.audioOutput).toString(); qDebug(logGui()) << "Got Audio Output: " << udpPrefs.audioOutput; - ui->audioOutputCombo->setEnabled(ui->lanEnableBtn->isChecked()); + //ui->audioOutputCombo->setEnabled(ui->lanEnableBtn->isChecked()); int audioOutputIndex = ui->audioOutputCombo->findText(udpPrefs.audioOutput); if (audioOutputIndex != -1) { ui->audioOutputCombo->setCurrentIndex(audioOutputIndex); @@ -871,7 +877,7 @@ void wfmain::loadSettings() udpPrefs.audioInput = settings.value("AudioInput", udpDefPrefs.audioInput).toString(); qDebug(logGui()) << "Got Audio Input: " << udpPrefs.audioInput; - ui->audioInputCombo->setEnabled(ui->lanEnableBtn->isChecked()); + //ui->audioInputCombo->setEnabled(ui->lanEnableBtn->isChecked()); int audioInputIndex = ui->audioInputCombo->findText(udpPrefs.audioInput); if (audioInputIndex != -1) { ui->audioInputCombo->setCurrentIndex(audioInputIndex); @@ -2918,6 +2924,14 @@ void wfmain::on_serialEnableBtn_clicked(bool checked) ui->controlPortTxt->setEnabled(!checked); ui->usernameTxt->setEnabled(!checked); ui->passwordTxt->setEnabled(!checked); + ui->audioRXCodecCombo->setEnabled(!checked); + ui->audioTXCodecCombo->setEnabled(!checked); + ui->audioSampleRateCombo->setEnabled(!checked); + ui->rxLatencySlider->setEnabled(!checked); + ui->txLatencySlider->setEnabled(!checked); + ui->rxLatencyValue->setEnabled(!checked); + ui->txLatencyValue->setEnabled(!checked); + } void wfmain::on_lanEnableBtn_clicked(bool checked)