From 387b26187de42a78a33edb1d79f915736e9a4ccb Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Mon, 17 Jan 2022 17:23:55 +0000 Subject: [PATCH] Initial server commit --- audiohandler.cpp | 2 +- main.cpp | 57 +- servermain.cpp | 1825 ++++++++++++++++++++++++++++++++++++++ servermain.h | 510 +++++++++++ wfmain.h | 5 + wfserver.pro | 158 ++++ wfserver.vcxproj | 313 +++++++ wfserver.vcxproj.filters | 284 ++++++ wfserver.vcxproj.user | 10 + wfserver_resource.rc | 37 + wfview.sln | 6 + wfview.vcxproj | 8 +- 12 files changed, 3186 insertions(+), 29 deletions(-) create mode 100644 servermain.cpp create mode 100644 servermain.h create mode 100644 wfserver.pro create mode 100644 wfserver.vcxproj create mode 100644 wfserver.vcxproj.filters create mode 100644 wfserver.vcxproj.user create mode 100644 wfserver_resource.rc diff --git a/audiohandler.cpp b/audiohandler.cpp index fc3dc94..56d7b67 100644 --- a/audiohandler.cpp +++ b/audiohandler.cpp @@ -98,7 +98,7 @@ bool audioHandler::init(audioSetup setupIn) ", uLaw" << setup.ulaw; - ringBuf = new wilt::Ring(setupIn.latency / 20 + 1); // Should be customizable. + ringBuf = new wilt::Ring(setup.latency / 20 + 1); // Should be customizable. tempBuf.sent = 0; diff --git a/main.cpp b/main.cpp index bae6e35..0adc1ad 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,10 @@ +//#undef WFSERVER +#ifdef WFSERVER +#include +#else #include +#endif + #include #include "wfmain.h" #include "logcategories.h" @@ -14,7 +20,12 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt int main(int argc, char *argv[]) { +#ifdef WFSERVER + QCoreApplication a(argc, argv); +#else QApplication a(argc, argv); +#endif + //a.setStyle( "Fusion" ); a.setOrganizationName("wfview"); @@ -38,12 +49,19 @@ int main(int argc, char *argv[]) const QString helpText = QString("\nUsage: -p --port /dev/port, -h --host remotehostname, -c --civ 0xAddr, -l --logfile filename.log, -s --settings filename.ini, -d --debug, -v --version\n"); // TODO... +#ifdef WFSERVER + const QString version = QString("wfserver version: %1 (Git:%2 on %3 at %4 by %5@%6)\nOperating System: %7 (%8)\nBuild Qt Version %9. Current Qt Version: %10\n") + .arg(QString(WFVIEW_VERSION)) + .arg(GITSHORT).arg(__DATE__).arg(__TIME__).arg(UNAME).arg(HOST) + .arg(QSysInfo::prettyProductName()).arg(QSysInfo::buildCpuArchitecture()) + .arg(QT_VERSION_STR).arg(qVersion()); +#else const QString version = QString("wfview version: %1 (Git:%2 on %3 at %4 by %5@%6)\nOperating System: %7 (%8)\nBuild Qt Version %9. Current Qt Version: %10\n") - .arg(QString(WFVIEW_VERSION)) - .arg(GITSHORT).arg(__DATE__).arg(__TIME__).arg(UNAME).arg(HOST) - .arg(QSysInfo::prettyProductName()).arg(QSysInfo::buildCpuArchitecture()) - .arg(QT_VERSION_STR).arg(qVersion()); - + .arg(QString(WFVIEW_VERSION)) + .arg(GITSHORT).arg(__DATE__).arg(__TIME__).arg(UNAME).arg(HOST) + .arg(QSysInfo::prettyProductName()).arg(QSysInfo::buildCpuArchitecture()) + .arg(QT_VERSION_STR).arg(qVersion()); +#endif for(int c=1; cserialPortCL = serialPortCL; + this->hostCL = hostCL; + + qRegisterMetaType(); // Needs to be registered early. + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType (); + qRegisterMetaType (); + qRegisterMetaType (); + qRegisterMetaType (); + qRegisterMetaType(); + + //signal(SIGINT, handleCtrlC); + + haveRigCaps = false; + + setDefPrefs(); + + getSettingsFilePath(settingsFile); + + loadSettings(); // Look for saved preferences + + setInitialTiming(); + + openRig(); + + rigConnections(); + + setServerToPrefs(); + + amTransmitting = false; + +} + +servermain::~servermain() +{ + rigThread->quit(); + rigThread->wait(); + if (serverThread != Q_NULLPTR) { + serverThread->quit(); + serverThread->wait(); + } + if (rigCtl != Q_NULLPTR) { + delete rigCtl; + } + delete settings; + +#if defined(PORTAUDIO) + Pa_Terminate(); +#endif + +} + +void servermain::closeEvent(QCloseEvent *event) +{ + // Are you sure? +} + +void servermain::openRig() +{ + // This function is intended to handle opening a connection to the rig. + // the connection can be either serial or network, + // and this function is also responsible for initiating the search for a rig model and capabilities. + // Any errors, such as unable to open connection or unable to open port, are to be reported to the user. + + //TODO: if(hasRunPreviously) + + //TODO: if(useNetwork){... + + // } else { + + // if (prefs.fileWasNotFound) { + // showRigSettings(); // rig setting dialog box for network/serial, CIV, hostname, port, baud rate, serial device, etc + // TODO: How do we know if the setting was loaded? + + + // TODO: Use these if they are found + if(!serialPortCL.isEmpty()) + { + qDebug(logSystem()) << "Serial port specified by user: " << serialPortCL; + } else { + qDebug(logSystem()) << "Serial port not specified. "; + } + + if(!hostCL.isEmpty()) + { + qDebug(logSystem()) << "Remote host name specified by user: " << hostCL; + } + + + makeRig(); + + if (prefs.enableLAN) + { + usingLAN = true; + // We need to setup the tx/rx audio: + emit sendCommSetup(prefs.radioCIVAddr, udpPrefs, rxSetup, txSetup, prefs.virtualSerialPort); + } else { + if( (prefs.serialPortRadio.toLower() == QString("auto")) && (serialPortCL.isEmpty())) + { + findSerialPort(); + + } else { + if(serialPortCL.isEmpty()) + { + serialPortRig = prefs.serialPortRadio; + } else { + serialPortRig = serialPortCL; + } + } + usingLAN = false; + emit sendCommSetup(prefs.radioCIVAddr, serialPortRig, prefs.serialPortBaud,prefs.virtualSerialPort); + } + + + +} + +void servermain::rigConnections() +{ + connect(this, SIGNAL(setCIVAddr(unsigned char)), rig, SLOT(setCIVAddr(unsigned char))); + + connect(this, SIGNAL(sendPowerOn()), rig, SLOT(powerOn())); + connect(this, SIGNAL(sendPowerOff()), rig, SLOT(powerOff())); + + connect(rig, SIGNAL(haveFrequency(freqt)), this, SLOT(receiveFreq(freqt))); + connect(this, SIGNAL(getFrequency()), rig, SLOT(getFrequency())); + connect(this, SIGNAL(getMode()), rig, SLOT(getMode())); + connect(this, SIGNAL(getDataMode()), rig, SLOT(getDataMode())); + connect(this, SIGNAL(setDataMode(bool, unsigned char)), rig, SLOT(setDataMode(bool, unsigned char))); + connect(this, SIGNAL(getBandStackReg(char,char)), rig, SLOT(getBandStackReg(char,char))); + connect(rig, SIGNAL(havePTTStatus(bool)), this, SLOT(receivePTTstatus(bool))); + connect(this, SIGNAL(setPTT(bool)), rig, SLOT(setPTT(bool))); + connect(this, SIGNAL(getPTT()), rig, SLOT(getPTT())); + connect(rig, SIGNAL(haveBandStackReg(freqt,char,char,bool)), this, SLOT(receiveBandStackReg(freqt,char,char,bool))); + connect(this, SIGNAL(setRitEnable(bool)), rig, SLOT(setRitEnable(bool))); + connect(this, SIGNAL(setRitValue(int)), rig, SLOT(setRitValue(int))); + connect(rig, SIGNAL(haveRitEnabled(bool)), this, SLOT(receiveRITStatus(bool))); + connect(rig, SIGNAL(haveRitFrequency(int)), this, SLOT(receiveRITValue(int))); + connect(this, SIGNAL(getRitEnabled()), rig, SLOT(getRitEnabled())); + connect(this, SIGNAL(getRitValue()), rig, SLOT(getRitValue())); + + connect(this, SIGNAL(getDebug()), rig, SLOT(getDebug())); + + connect(this, SIGNAL(spectOutputDisable()), rig, SLOT(disableSpectOutput())); + connect(this, SIGNAL(spectOutputEnable()), rig, SLOT(enableSpectOutput())); + connect(this, SIGNAL(scopeDisplayDisable()), rig, SLOT(disableSpectrumDisplay())); + connect(this, SIGNAL(scopeDisplayEnable()), rig, SLOT(enableSpectrumDisplay())); + connect(rig, SIGNAL(haveDataMode(bool)), this, SLOT(receiveDataModeStatus(bool))); + + + connect(this, SIGNAL(getDuplexMode()), rig, SLOT(getDuplexMode())); + connect(this, SIGNAL(getTone()), rig, SLOT(getTone())); + connect(this, SIGNAL(getTSQL()), rig, SLOT(getTSQL())); + connect(this, SIGNAL(getRptAccessMode()), rig, SLOT(getRptAccessMode())); + //connect(this, SIGNAL(setDuplexMode(duplexMode)), rig, SLOT(setDuplexMode(duplexMode))); + //connect(rig, SIGNAL(haveDuplexMode(duplexMode)), this, SLOT(receiveDuplexMode(duplexMode))); + + connect(this, SIGNAL(getModInput(bool)), rig, SLOT(getModInput(bool))); + connect(rig, SIGNAL(haveModInput(rigInput,bool)), this, SLOT(receiveModInput(rigInput, bool))); + connect(this, SIGNAL(setModInput(rigInput, bool)), rig, SLOT(setModInput(rigInput,bool))); + + connect(rig, SIGNAL(haveSpectrumData(QByteArray, double, double)), this, SLOT(receiveSpectrumData(QByteArray, double, double))); + connect(rig, SIGNAL(haveSpectrumMode(spectrumMode)), this, SLOT(receiveSpectrumMode(spectrumMode))); + connect(this, SIGNAL(setScopeMode(spectrumMode)), rig, SLOT(setSpectrumMode(spectrumMode))); + connect(this, SIGNAL(getScopeMode()), rig, SLOT(getScopeMode())); + + connect(this, SIGNAL(setFrequency(unsigned char, freqt)), rig, SLOT(setFrequency(unsigned char, freqt))); + connect(this, SIGNAL(setScopeEdge(char)), rig, SLOT(setScopeEdge(char))); + connect(this, SIGNAL(setScopeSpan(char)), rig, SLOT(setScopeSpan(char))); + //connect(this, SIGNAL(getScopeMode()), rig, SLOT(getScopeMode())); + connect(this, SIGNAL(getScopeEdge()), rig, SLOT(getScopeEdge())); + connect(this, SIGNAL(getScopeSpan()), rig, SLOT(getScopeSpan())); + connect(rig, SIGNAL(haveScopeSpan(freqt,bool)), this, SLOT(receiveSpectrumSpan(freqt,bool))); + connect(this, SIGNAL(setScopeFixedEdge(double,double,unsigned char)), rig, SLOT(setSpectrumBounds(double,double,unsigned char))); + + connect(this, SIGNAL(setMode(unsigned char, unsigned char)), rig, SLOT(setMode(unsigned char, unsigned char))); + connect(this, SIGNAL(setMode(mode_info)), rig, SLOT(setMode(mode_info))); + + // Levels (read and write) + // Levels: Query: + connect(this, SIGNAL(getLevels()), rig, SLOT(getLevels())); + connect(this, SIGNAL(getRfGain()), rig, SLOT(getRfGain())); + connect(this, SIGNAL(getAfGain()), rig, SLOT(getAfGain())); + connect(this, SIGNAL(getSql()), rig, SLOT(getSql())); + connect(this, SIGNAL(getIfShift()), rig, SLOT(getIFShift())); + connect(this, SIGNAL(getTPBFInner()), rig, SLOT(getTPBFInner())); + connect(this, SIGNAL(getTPBFOuter()), rig, SLOT(getTPBFOuter())); + connect(this, SIGNAL(getTxPower()), rig, SLOT(getTxLevel())); + connect(this, SIGNAL(getMicGain()), rig, SLOT(getMicGain())); + connect(this, SIGNAL(getSpectrumRefLevel()), rig, SLOT(getSpectrumRefLevel())); + connect(this, SIGNAL(getModInputLevel(rigInput)), rig, SLOT(getModInputLevel(rigInput))); + + + // Levels: Set: + connect(this, SIGNAL(setRfGain(unsigned char)), rig, SLOT(setRfGain(unsigned char))); + connect(this, SIGNAL(setAfGain(unsigned char)), rig, SLOT(setAfGain(unsigned char))); + connect(this, SIGNAL(setSql(unsigned char)), rig, SLOT(setSquelch(unsigned char))); + connect(this, SIGNAL(setIFShift(unsigned char)), rig, SLOT(setIFShift(unsigned char))); + connect(this, SIGNAL(setTPBFInner(unsigned char)), rig, SLOT(setTPBFInner(unsigned char))); + connect(this, SIGNAL(setTPBFOuter(unsigned char)), rig, SLOT(setTPBFOuter(unsigned char))); + connect(this, SIGNAL(setTxPower(unsigned char)), rig, SLOT(setTxPower(unsigned char))); + connect(this, SIGNAL(setMicGain(unsigned char)), rig, SLOT(setMicGain(unsigned char))); + connect(this, SIGNAL(setMonitorLevel(unsigned char)), rig, SLOT(setMonitorLevel(unsigned char))); + connect(this, SIGNAL(setVoxGain(unsigned char)), rig, SLOT(setVoxGain(unsigned char))); + connect(this, SIGNAL(setAntiVoxGain(unsigned char)), rig, SLOT(setAntiVoxGain(unsigned char))); + connect(this, SIGNAL(setSpectrumRefLevel(int)), rig, SLOT(setSpectrumRefLevel(int))); + connect(this, SIGNAL(setModLevel(rigInput, unsigned char)), rig, SLOT(setModInputLevel(rigInput, unsigned char))); + + // Levels: handle return on query: + connect(rig, SIGNAL(haveRfGain(unsigned char)), this, SLOT(receiveRfGain(unsigned char))); + connect(rig, SIGNAL(haveAfGain(unsigned char)), this, SLOT(receiveAfGain(unsigned char))); + connect(rig, SIGNAL(haveSql(unsigned char)), this, SLOT(receiveSql(unsigned char))); + connect(rig, SIGNAL(haveTxPower(unsigned char)), this, SLOT(receiveTxPower(unsigned char))); + connect(rig, SIGNAL(haveMicGain(unsigned char)), this, SLOT(receiveMicGain(unsigned char))); + connect(rig, SIGNAL(haveSpectrumRefLevel(int)), this, SLOT(receiveSpectrumRefLevel(int))); + connect(rig, SIGNAL(haveACCGain(unsigned char,unsigned char)), this, SLOT(receiveACCGain(unsigned char,unsigned char))); + connect(rig, SIGNAL(haveUSBGain(unsigned char)), this, SLOT(receiveUSBGain(unsigned char))); + connect(rig, SIGNAL(haveLANGain(unsigned char)), this, SLOT(receiveLANGain(unsigned char))); + + //Metering: + connect(this, SIGNAL(getMeters(meterKind)), rig, SLOT(getMeters(meterKind))); + connect(rig, SIGNAL(haveMeter(meterKind,unsigned char)), this, SLOT(receiveMeter(meterKind,unsigned char))); + + // Rig and ATU info: + connect(this, SIGNAL(startATU()), rig, SLOT(startATU())); + connect(this, SIGNAL(setATU(bool)), rig, SLOT(setATU(bool))); + connect(this, SIGNAL(getATUStatus()), rig, SLOT(getATUStatus())); + connect(this, SIGNAL(getRigID()), rig, SLOT(getRigID())); + connect(rig, SIGNAL(haveATUStatus(unsigned char)), this, SLOT(receiveATUStatus(unsigned char))); + connect(rig, SIGNAL(haveRigID(rigCapabilities)), this, SLOT(receiveRigID(rigCapabilities))); + connect(this, SIGNAL(setAttenuator(unsigned char)), rig, SLOT(setAttenuator(unsigned char))); + connect(this, SIGNAL(setPreamp(unsigned char)), rig, SLOT(setPreamp(unsigned char))); + connect(this, SIGNAL(setAntenna(unsigned char, bool)), rig, SLOT(setAntenna(unsigned char, bool))); + connect(this, SIGNAL(getPreamp()), rig, SLOT(getPreamp())); + connect(rig, SIGNAL(havePreamp(unsigned char)), this, SLOT(receivePreamp(unsigned char))); + connect(this, SIGNAL(getAttenuator()), rig, SLOT(getAttenuator())); + connect(rig, SIGNAL(haveAttenuator(unsigned char)), this, SLOT(receiveAttenuator(unsigned char))); + connect(this, SIGNAL(getAntenna()), rig, SLOT(getAntenna())); + connect(rig, SIGNAL(haveAntenna(unsigned char,bool)), this, SLOT(receiveAntennaSel(unsigned char,bool))); + + + // Speech (emitted from rig speaker) + connect(this, SIGNAL(sayAll()), rig, SLOT(sayAll())); + connect(this, SIGNAL(sayFrequency()), rig, SLOT(sayFrequency())); + connect(this, SIGNAL(sayMode()), rig, SLOT(sayMode())); + + + // Date and Time: + connect(this, SIGNAL(setTime(timekind)), rig, SLOT(setTime(timekind))); + connect(this, SIGNAL(setDate(datekind)), rig, SLOT(setDate(datekind))); + connect(this, SIGNAL(setUTCOffset(timekind)), rig, SLOT(setUTCOffset(timekind))); + +} + + +void servermain::makeRig() +{ + if (rigThread == Q_NULLPTR) + { + rig = new rigCommander(); + rigThread = new QThread(this); + + // Thread: + rig->moveToThread(rigThread); + connect(rigThread, SIGNAL(started()), rig, SLOT(process())); + connect(rigThread, SIGNAL(finished()), rig, SLOT(deleteLater())); + rigThread->start(); + + // Rig status and Errors: + connect(rig, SIGNAL(haveSerialPortError(QString, QString)), this, SLOT(receiveSerialPortError(QString, QString))); + connect(rig, SIGNAL(haveStatusUpdate(QString)), this, SLOT(receiveStatusUpdate(QString))); + + // Rig comm setup: + connect(this, SIGNAL(sendCommSetup(unsigned char, udpPreferences, audioSetup, audioSetup, QString)), rig, SLOT(commSetup(unsigned char, udpPreferences, audioSetup, audioSetup, QString))); + connect(this, SIGNAL(sendCommSetup(unsigned char, QString, quint32,QString)), rig, SLOT(commSetup(unsigned char, QString, quint32,QString))); + connect(this, SIGNAL(setRTSforPTT(bool)), rig, SLOT(setRTSforPTT(bool))); + + connect(rig, SIGNAL(haveBaudRate(quint32)), this, SLOT(receiveBaudRate(quint32))); + + connect(this, SIGNAL(sendCloseComm()), rig, SLOT(closeComm())); + connect(this, SIGNAL(sendChangeLatency(quint16)), rig, SLOT(changeLatency(quint16))); + connect(this, SIGNAL(getRigCIV()), rig, SLOT(findRigs())); + connect(this, SIGNAL(setRigID(unsigned char)), rig, SLOT(setRigID(unsigned char))); + connect(rig, SIGNAL(discoveredRigID(rigCapabilities)), this, SLOT(receiveFoundRigID(rigCapabilities))); + connect(rig, SIGNAL(commReady()), this, SLOT(receiveCommReady())); + + connect(this, SIGNAL(requestRigState()), rig, SLOT(sendState())); + connect(this, SIGNAL(stateUpdated()), rig, SLOT(stateUpdated())); + connect(rig, SIGNAL(stateInfo(rigstate*)), this, SLOT(receiveStateInfo(rigstate*))); + if (rigCtl != Q_NULLPTR) { + connect(rig, SIGNAL(stateInfo(rigstate*)), rigCtl, SLOT(receiveStateInfo(rigstate*))); + connect(rigCtl, SIGNAL(stateUpdated()), rig, SLOT(stateUpdated())); + } + } +} + +void servermain::removeRig() +{ + if (rigThread != Q_NULLPTR) + { + if (rigCtl != Q_NULLPTR) { + rigCtl->disconnect(); + } + rigThread->disconnect(); + + rig->disconnect(); + + delete rigThread; + delete rig; + rig = Q_NULLPTR; + } + +} + + +void servermain::findSerialPort() +{ + // Find the ICOM radio connected, or, if none, fall back to OS default. + // qInfo(logSystem()) << "Searching for serial port..."; + QDirIterator it73("/dev/serial/by-id", QStringList() << "*IC-7300*", QDir::Files, QDirIterator::Subdirectories); + QDirIterator it97("/dev/serial", QStringList() << "*IC-9700*A*", QDir::Files, QDirIterator::Subdirectories); + QDirIterator it785x("/dev/serial", QStringList() << "*IC-785*A*", QDir::Files, QDirIterator::Subdirectories); + QDirIterator it705("/dev/serial", QStringList() << "*IC-705*A", QDir::Files, QDirIterator::Subdirectories); + QDirIterator it7610("/dev/serial", QStringList() << "*IC-7610*A", QDir::Files, QDirIterator::Subdirectories); + QDirIterator itR8600("/dev/serial", QStringList() << "*IC-R8600*A", QDir::Files, QDirIterator::Subdirectories); + + if(!it73.filePath().isEmpty()) + { + // IC-7300 + serialPortRig = it73.filePath(); // first + } else if(!it97.filePath().isEmpty()) + { + // IC-9700 + serialPortRig = it97.filePath(); + } else if(!it785x.filePath().isEmpty()) + { + // IC-785x + serialPortRig = it785x.filePath(); + } else if(!it705.filePath().isEmpty()) + { + // IC-705 + serialPortRig = it705.filePath(); + } else if(!it7610.filePath().isEmpty()) + { + // IC-7610 + serialPortRig = it7610.filePath(); + } else if(!itR8600.filePath().isEmpty()) + { + // IC-R8600 + serialPortRig = itR8600.filePath(); + } else { + //fall back: + qInfo(logSystem()) << "Could not find Icom serial port. Falling back to OS default. Use --port to specify, or modify preferences."; +#ifdef Q_OS_MAC + serialPortRig = QString("/dev/tty.SLAB_USBtoUART"); +#endif +#ifdef Q_OS_LINUX + serialPortRig = QString("/dev/ttyUSB0"); +#endif +#ifdef Q_OS_WIN + serialPortRig = QString("COM1"); +#endif + } +} + +void servermain::receiveCommReady() +{ + qInfo(logSystem()) << "Received CommReady!! "; + if(!usingLAN) + { + // usingLAN gets set when we emit the sendCommSetup signal. + // If we're not using the LAN, then we're on serial, and + // we already know the baud rate and can calculate the timing parameters. + calculateTimingParameters(); + } + if(prefs.radioCIVAddr == 0) + { + // tell rigCommander to broadcast a request for all rig IDs. + // qInfo(logSystem()) << "Beginning search from wfview for rigCIV (auto-detection broadcast)"; + emit getRigCIV(); + issueDelayedCommand(cmdGetRigCIV); + delayedCommand->start(); + } else { + // don't bother, they told us the CIV they want, stick with it. + // We still query the rigID to find the model, but at least we know the CIV. + qInfo(logSystem()) << "Skipping automatic CIV, using user-supplied value of " << prefs.radioCIVAddr; + if(prefs.CIVisRadioModel) + { + qInfo(logSystem()) << "Skipping Rig ID query, using user-supplied model from CI-V address: " << prefs.radioCIVAddr; + emit setRigID(prefs.radioCIVAddr); + } else { + emit getRigID(); + getInitialRigState(); + } + } +} + + +void servermain::receiveFoundRigID(rigCapabilities rigCaps) +{ + // Entry point for unknown rig being identified at the start of the program. + //now we know what the rig ID is: + //qInfo(logSystem()) << "In wfview, we now have a reply to our request for rig identity sent to CIV BROADCAST."; + + if(rig->usingLAN()) + { + usingLAN = true; + } else { + usingLAN = false; + } + + receiveRigID(rigCaps); + getInitialRigState(); + + return; +} + +void servermain::receiveSerialPortError(QString port, QString errorText) +{ + qInfo(logSystem()) << "servermain: received serial port error for port: " << port << " with message: " << errorText; + + // TODO: Dialog box, exit, etc +} + + +void servermain::getSettingsFilePath(QString settingsFile) +{ + if (settingsFile.isNull()) { + settings = new QSettings(); + } + else + { + QString file = settingsFile; + QFile info(settingsFile); + QString path=""; + if (!QFileInfo(info).isAbsolute()) + { + path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + if (path.isEmpty()) + { + path = QDir::homePath(); + } + path = path + "/"; + file = info.fileName(); + } + + qInfo(logSystem()) << "Loading settings from:" << path + file; + settings = new QSettings(path + file, QSettings::Format::IniFormat); + } +} + + +void servermain::setInitialTiming() +{ + loopTickCounter = 0; + delayedCmdIntervalLAN_ms = 70; // interval for regular delayed commands, including initial rig/UI state queries + delayedCmdIntervalSerial_ms = 100; // interval for regular delayed commands, including initial rig/UI state queries + delayedCmdStartupInterval_ms = 250; // interval for rigID polling + delayedCommand = new QTimer(this); + delayedCommand->setInterval(delayedCmdStartupInterval_ms); // 250ms until we find rig civ and id, then 100ms. + delayedCommand->setSingleShot(false); + connect(delayedCommand, SIGNAL(timeout()), this, SLOT(sendRadioCommandLoop())); + + // TODO: Remove this: +// periodicPollingTimer = new QTimer(this); +// periodicPollingTimer->setInterval(10); +// periodicPollingTimer->setSingleShot(false); + //connect(periodicPollingTimer, SIGNAL(timeout()), this, SLOT(sendRadioCommandLoop())); + + pttTimer = new QTimer(this); + pttTimer->setInterval(180*1000); // 3 minute max transmit time in ms + pttTimer->setSingleShot(true); + connect(pttTimer, SIGNAL(timeout()), this, SLOT(handlePttLimit())); + + timeSync = new QTimer(this); + connect(timeSync, SIGNAL(timeout()), this, SLOT(setRadioTimeDateSend())); + waitingToSetTimeDate = false; + lastFreqCmdTime_ms = QDateTime::currentMSecsSinceEpoch() - 5000; // 5 seconds ago +} + +void servermain::setServerToPrefs() +{ + + // Start server if enabled in config + if (serverThread != Q_NULLPTR) { + serverThread->quit(); + serverThread->wait(); + serverThread = Q_NULLPTR; + udp = Q_NULLPTR; + } + + if (serverConfig.enabled) { + serverConfig.lan = prefs.enableLAN; + qInfo(logAudio()) << "Audio Input device " << serverRxSetup.name; + qInfo(logAudio()) << "Audio Output device " << serverTxSetup.name; + udp = new udpServer(serverConfig, serverTxSetup, serverRxSetup); + + serverThread = new QThread(this); + + udp->moveToThread(serverThread); + + + connect(this, SIGNAL(initServer()), udp, SLOT(init())); + connect(serverThread, SIGNAL(finished()), udp, SLOT(deleteLater())); + + if (rig != Q_NULLPTR) { + connect(rig, SIGNAL(haveAudioData(audioPacket)), udp, SLOT(receiveAudioData(audioPacket))); + connect(rig, SIGNAL(haveDataForServer(QByteArray)), udp, SLOT(dataForServer(QByteArray))); + connect(udp, SIGNAL(haveDataFromServer(QByteArray)), rig, SLOT(dataFromServer(QByteArray))); + } + + if (!prefs.enableLAN) { + connect(udp, SIGNAL(haveNetworkStatus(QString)), this, SLOT(receiveStatusUpdate(QString))); + } + + serverThread->start(); + + emit initServer(); + + connect(this, SIGNAL(sendRigCaps(rigCapabilities)), udp, SLOT(receiveRigCaps(rigCapabilities))); + + } +} + + +void servermain::setDefPrefs() +{ + defPrefs.useFullScreen = false; + defPrefs.useDarkMode = true; + defPrefs.useSystemTheme = false; + defPrefs.drawPeaks = true; + defPrefs.wfAntiAlias = false; + defPrefs.wfInterpolate = true; + defPrefs.radioCIVAddr = 0x00; // previously was 0x94 for 7300. + defPrefs.CIVisRadioModel = false; + defPrefs.forceRTSasPTT = false; + defPrefs.serialPortRadio = QString("auto"); + defPrefs.serialPortBaud = 115200; + defPrefs.enablePTT = false; + defPrefs.niceTS = true; + defPrefs.enableRigCtlD = false; + defPrefs.rigCtlPort = 4533; + defPrefs.virtualSerialPort = QString("none"); + defPrefs.localAFgain = 255; + defPrefs.wflength = 160; + defPrefs.confirmExit = true; + defPrefs.confirmPowerOff = true; + defPrefs.meter2Type = meterNone; + + udpDefPrefs.ipAddress = QString(""); + udpDefPrefs.controlLANPort = 50001; + udpDefPrefs.serialLANPort = 50002; + udpDefPrefs.audioLANPort = 50003; + udpDefPrefs.username = QString(""); + udpDefPrefs.password = QString(""); + udpDefPrefs.clientName = QHostInfo::localHostName(); +} + +void servermain::loadSettings() +{ + qInfo(logSystem()) << "Loading settings from " << settings->fileName(); + + // Radio and Comms: C-IV addr, port to use + settings->beginGroup("Radio"); + prefs.radioCIVAddr = (unsigned char)settings->value("RigCIVuInt", defPrefs.radioCIVAddr).toInt(); + prefs.CIVisRadioModel = (bool)settings->value("CIVisRadioModel", defPrefs.CIVisRadioModel).toBool(); + prefs.forceRTSasPTT = (bool)settings->value("ForceRTSasPTT", defPrefs.forceRTSasPTT).toBool(); + prefs.serialPortRadio = settings->value("SerialPortRadio", defPrefs.serialPortRadio).toString(); + prefs.serialPortBaud = (quint32)settings->value("SerialPortBaud", defPrefs.serialPortBaud).toInt(); + + if (prefs.serialPortBaud > 0) + { + serverConfig.baudRate = prefs.serialPortBaud; + } + + prefs.virtualSerialPort = settings->value("VirtualSerialPort", defPrefs.virtualSerialPort).toString(); + + prefs.localAFgain = (unsigned char)settings->value("localAFgain", defPrefs.localAFgain).toUInt(); + rxSetup.localAFgain = prefs.localAFgain; + txSetup.localAFgain = 255; + + settings->endGroup(); + + // Misc. user settings (enable PTT, draw peaks, etc) + settings->beginGroup("Controls"); + prefs.enablePTT = settings->value("EnablePTT", defPrefs.enablePTT).toBool(); + prefs.niceTS = settings->value("NiceTS", defPrefs.niceTS).toBool(); + settings->endGroup(); + + settings->beginGroup("LAN"); + + prefs.enableLAN = settings->value("EnableLAN", defPrefs.enableLAN).toBool(); + + prefs.enableRigCtlD = settings->value("EnableRigCtlD", defPrefs.enableRigCtlD).toBool(); + prefs.rigCtlPort = settings->value("RigCtlPort", defPrefs.rigCtlPort).toInt(); + udpPrefs.ipAddress = settings->value("IPAddress", udpDefPrefs.ipAddress).toString(); + udpPrefs.controlLANPort = settings->value("ControlLANPort", udpDefPrefs.controlLANPort).toInt(); + udpPrefs.username = settings->value("Username", udpDefPrefs.username).toString(); + udpPrefs.password = settings->value("Password", udpDefPrefs.password).toString(); + + rxSetup.isinput = false; + txSetup.isinput = true; + + rxSetup.latency = settings->value("AudioRXLatency", "150").toInt(); + txSetup.latency = settings->value("AudioTXLatency", "150").toInt(); + rxSetup.samplerate = settings->value("AudioRXSampleRate", "48000").toInt(); + txSetup.samplerate = rxSetup.samplerate; + rxSetup.codec = settings->value("AudioRXCodec", "4").toInt(); + txSetup.codec = settings->value("AudioTXCodec", "4").toInt(); + rxSetup.name = settings->value("AudioOutput", "").toString(); + qInfo(logGui()) << "Got Audio Output: " << rxSetup.name; + + txSetup.name = settings->value("AudioInput", "").toString(); + // qInfo(logGui()) << "Got Audio Input: " << txSetup.name; int audioInputIndex = ui->audioInputCombo->findText(txSetup.name); + + rxSetup.resampleQuality = settings->value("ResampleQuality", "4").toInt(); + txSetup.resampleQuality = rxSetup.resampleQuality; + + udpPrefs.clientName = settings->value("ClientName", udpDefPrefs.clientName).toString(); + + settings->endGroup(); + + + settings->beginGroup("Server"); + serverConfig.enabled = settings->value("ServerEnabled", false).toBool(); + serverConfig.controlPort = settings->value("ServerControlPort", 50001).toInt(); + serverConfig.civPort = settings->value("ServerCivPort", 50002).toInt(); + serverConfig.audioPort = settings->value("ServerAudioPort", 50003).toInt(); + int numUsers = settings->value("ServerNumUsers", 2).toInt(); + serverConfig.users.clear(); + for (int f = 0; f < numUsers; f++) + { + SERVERUSER user; + user.username = settings->value("ServerUsername_" + QString::number(f), "").toString(); + user.password = settings->value("ServerPassword_" + QString::number(f), "").toString(); + user.userType = settings->value("ServerUserType_" + QString::number(f), 0).toInt(); + serverConfig.users.append(user); + } + + serverRxSetup.isinput = true; + serverTxSetup.isinput = false; + serverRxSetup.localAFgain = 255; + serverTxSetup.localAFgain = 255; + + serverRxSetup.name = settings->value("ServerAudioInput", "").toString(); + qInfo(logGui()) << "Got Server Audio Input: " << serverRxSetup.name; + + serverRxSetup.resampleQuality = rxSetup.resampleQuality; + serverTxSetup.resampleQuality = serverRxSetup.resampleQuality; + + serverTxSetup.name = settings->value("ServerAudioOutput", "").toString(); + qInfo(logGui()) << "Got Server Audio Output: " << serverTxSetup.name; + + settings->endGroup(); + + // Memory channels + + settings->beginGroup("Memory"); + int size = settings->beginReadArray("Channel"); + int chan = 0; + double freq; + unsigned char mode; + bool isSet; + + // Annoying: QSettings will write the array to the + // preference file starting the array at 1 and ending at 100. + // Thus, we are writing the channel number each time. + // It is also annoying that they get written with their array + // numbers in alphabetical order without zero padding. + // Also annoying that the preference groups are not written in + // the order they are specified here. + + for (int i = 0; i < size; i++) + { + settings->setArrayIndex(i); + chan = settings->value("chan", 0).toInt(); + freq = settings->value("freq", 12.345).toDouble(); + mode = settings->value("mode", 0).toInt(); + isSet = settings->value("isSet", false).toBool(); + + if (isSet) + { + mem.setPreset(chan, freq, (mode_kind)mode); + } + } + + settings->endArray(); + settings->endGroup(); + + + + + +#if defined(RTAUDIO) + +#if defined(Q_OS_LINUX) + RtAudio* audio = new RtAudio(RtAudio::Api::LINUX_ALSA); +#elif defined(Q_OS_WIN) + RtAudio* audio = new RtAudio(RtAudio::Api::WINDOWS_WASAPI); +#elif defined(Q_OS_MACX) + RtAudio* audio = new RtAudio(RtAudio::Api::MACOSX_CORE); +#endif + + // Enumerate audio devices, need to do before settings are loaded. + std::map apiMap; + apiMap[RtAudio::MACOSX_CORE] = "OS-X Core Audio"; + apiMap[RtAudio::WINDOWS_ASIO] = "Windows ASIO"; + apiMap[RtAudio::WINDOWS_DS] = "Windows DirectSound"; + apiMap[RtAudio::WINDOWS_WASAPI] = "Windows WASAPI"; + apiMap[RtAudio::UNIX_JACK] = "Jack Client"; + apiMap[RtAudio::LINUX_ALSA] = "Linux ALSA"; + apiMap[RtAudio::LINUX_PULSE] = "Linux PulseAudio"; + apiMap[RtAudio::LINUX_OSS] = "Linux OSS"; + apiMap[RtAudio::RTAUDIO_DUMMY] = "RtAudio Dummy"; + + std::vector< RtAudio::Api > apis; + RtAudio::getCompiledApi(apis); + + qInfo(logAudio()) << "RtAudio Version " << QString::fromStdString(RtAudio::getVersion()); + + qInfo(logAudio()) << "Compiled APIs:"; + for (unsigned int i = 0; i < apis.size(); i++) { + qInfo(logAudio()) << " " << QString::fromStdString(apiMap[apis[i]]); + } + + RtAudio::DeviceInfo info; + + qInfo(logAudio()) << "Current API: " << QString::fromStdString(apiMap[audio->getCurrentApi()]); + + unsigned int devices = audio->getDeviceCount(); + qInfo(logAudio()) << "Found " << devices << " audio device(s) *=default"; + + for (unsigned int i = 1; i < devices; i++) { + info = audio->getDeviceInfo(i); + if (info.outputChannels > 0) { + if (QString::fromStdString(info.name) == rxSetup.name) { + rxSetup.port = i; + } + if (QString::fromStdString(info.name) == serverTxSetup.name) { + serverTxSetup.port = i; + } + } + if (info.inputChannels > 0) { + if (QString::fromStdString(info.name) == txSetup.name) { + txSetup.port = i; + } + if (QString::fromStdString(info.name) == serverRxSetup.name) { + serverRxSetup.port = i; + } + } + } + + delete audio; + +#elif defined(PORTAUDIO) + // Use PortAudio device enumeration + + PaError err; + + err = Pa_Initialize(); + + if (err != paNoError) + { + qInfo(logAudio()) << "ERROR: Cannot initialize Portaudio"; + } + + qInfo(logAudio()) << "PortAudio version: " << Pa_GetVersionInfo()->versionText; + + int numDevices; + numDevices = Pa_GetDeviceCount(); + qInfo(logAudio()) << "Pa_CountDevices returned" << numDevices; + + const PaDeviceInfo* info; + for (int i = 0; i < numDevices; i++) + { + info = Pa_GetDeviceInfo(i); + if (info->maxInputChannels > 0) { + if (QString::fromStdString(info.name) == rxSetup.name) { + rxSetup.port = i; + } + if (QString::fromStdString(info.name) == serverTxSetup.name) { + serverTxSetup.port = i; + } + } + if (info->maxOutputChannels > 0) { + if (QString::fromStdString(info.name) == txSetup.name) { + txSetup.port = i; + } + if (QString::fromStdString(info.name) == serverRxSetup.name) { + serverRxSetup.port = i; + } + } + } +#else + + // If no external library is configured, use QTMultimedia + // + // Set these to default audio devices initially. + rxSetup.port = QAudioDeviceInfo::defaultOutputDevice(); + txSetup.port = QAudioDeviceInfo::defaultInputDevice(); + serverRxSetup.port = QAudioDeviceInfo::defaultInputDevice(); + serverTxSetup.port = QAudioDeviceInfo::defaultOutputDevice(); + + + // Enumerate audio devices, need to do before settings are loaded. + const auto audioOutputs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput); + for (const QAudioDeviceInfo& deviceInfo : audioOutputs) { + if (deviceInfo.deviceName() == rxSetup.name) { + rxSetup.port = deviceInfo; + qInfo(logGui()) << "Setting Audio Output: " << rxSetup.name; + } + if (deviceInfo.deviceName() == serverTxSetup.name) { + serverTxSetup.port = deviceInfo; + qInfo(logGui()) << "Setting Server Audio Input: " << serverTxSetup.name; + } + } + + const auto audioInputs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + for (const QAudioDeviceInfo& deviceInfo : audioInputs) { + if (deviceInfo.deviceName() == txSetup.name) { + txSetup.port = deviceInfo; + qInfo(logGui()) << "Setting Audio Input: " << txSetup.name; + } + if (deviceInfo.deviceName() == serverRxSetup.name) { + serverRxSetup.port = deviceInfo; + qInfo(logGui()) << "Setting Server Audio Output: " << serverRxSetup.name; + } + } + +#endif + +} + + +quint64 servermain::roundFrequency(quint64 frequency, unsigned int tsHz) +{ + return frequency; +} + +quint64 servermain::roundFrequencyWithStep(quint64 frequency, int steps, unsigned int tsHz) +{ + quint64 rounded = 0; + + if(steps > 0) + { + frequency = frequency + (quint64)(steps*tsHz); + } else { + frequency = frequency - std::min((quint64)(abs(steps)*tsHz), frequency); + } + + return frequency; +} + + +void servermain:: getInitialRigState() +{ + // Initial list of queries to the radio. + // These are made when the program starts up + // and are used to adjust the UI to match the radio settings + // the polling interval is set at 200ms. Faster is possible but slower + // computers will glitch occassionally. + + issueDelayedCommand(cmdGetFreq); + issueDelayedCommand(cmdGetMode); + + issueDelayedCommand(cmdNone); + + issueDelayedCommand(cmdGetFreq); + issueDelayedCommand(cmdGetMode); + + // From left to right in the UI: + if (rigCaps.hasTransmit) + { + issueDelayedCommand(cmdGetDataMode); + issueDelayedCommand(cmdGetModInput); + issueDelayedCommand(cmdGetModDataInput); + } + issueDelayedCommand(cmdGetRxGain); + issueDelayedCommand(cmdGetAfGain); + issueDelayedCommand(cmdGetSql); + + if (rigCaps.hasTransmit) + { + issueDelayedCommand(cmdGetTxPower); + issueDelayedCommand(cmdGetCurrentModLevel); // level for currently selected mod sources + } + + issueDelayedCommand(cmdGetSpectrumRefLevel); + issueDelayedCommand(cmdGetDuplexMode); + + if(rigCaps.hasSpectrum) + { + issueDelayedCommand(cmdDispEnable); + issueDelayedCommand(cmdSpecOn); + } + + if (rigCaps.hasTransmit) + { + issueDelayedCommand(cmdGetModInput); + issueDelayedCommand(cmdGetModDataInput); + } + + if(rigCaps.hasCTCSS) + { + issueDelayedCommand(cmdGetTone); + issueDelayedCommand(cmdGetTSQL); + } + if(rigCaps.hasDTCS) + { + issueDelayedCommand(cmdGetDTCS); + } + issueDelayedCommand(cmdGetRptAccessMode); + + if(rigCaps.hasAntennaSel) + { + issueDelayedCommand(cmdGetAntenna); + } + if(rigCaps.hasAttenuator) + { + issueDelayedCommand(cmdGetAttenuator); + } + if(rigCaps.hasPreamp) + { + issueDelayedCommand(cmdGetPreamp); + } + + issueDelayedCommand(cmdGetRitEnabled); + issueDelayedCommand(cmdGetRitValue); + + if(rigCaps.hasIFShift) + issueDelayedCommand(cmdGetIFShift); + if(rigCaps.hasTBPF) + { + issueDelayedCommand(cmdGetTPBFInner); + issueDelayedCommand(cmdGetTPBFOuter); + } + + if(rigCaps.hasSpectrum) + { + issueDelayedCommand(cmdGetSpectrumMode); + issueDelayedCommand(cmdGetSpectrumSpan); + } + + issueDelayedCommand(cmdNone); + issueDelayedCommand(cmdStartRegularPolling); + + if(rigCaps.hasATU) + { + issueDelayedCommand(cmdGetATUStatus); + } + + delayedCommand->start(); +} + + +void servermain::doCmd(commandtype cmddata) +{ + cmds cmd = cmddata.cmd; + std::shared_ptr data = cmddata.data; + + // This switch is for commands with parameters. + // the "default" for non-parameter commands is to call doCmd(cmd). + switch (cmd) + { + case cmdSetFreq: + { + lastFreqCmdTime_ms = QDateTime::currentMSecsSinceEpoch(); + freqt f = (*std::static_pointer_cast(data)); + emit setFrequency(0,f); + break; + } + case cmdSetMode: + { + mode_info m = (*std::static_pointer_cast(data)); + emit setMode(m); + break; + } + case cmdSetTxPower: + { + unsigned char txpower = (*std::static_pointer_cast(data)); + emit setTxPower(txpower); + break; + } + case cmdSetMicGain: + { + unsigned char micgain = (*std::static_pointer_cast(data)); + emit setTxPower(micgain); + break; + } + case cmdSetRxRfGain: + { + unsigned char rfgain = (*std::static_pointer_cast(data)); + emit setRfGain(rfgain); + break; + } + case cmdSetModLevel: + { + unsigned char modlevel = (*std::static_pointer_cast(data)); + rigInput currentIn; + if(usingDataMode) + { + currentIn = currentModDataSrc; + } else { + currentIn = currentModSrc; + } + emit setModLevel(currentIn, modlevel); + break; + } + case cmdSetAfGain: + { + unsigned char afgain = (*std::static_pointer_cast(data)); + emit setAfGain(afgain); + break; + } + case cmdSetSql: + { + unsigned char sqlLevel = (*std::static_pointer_cast(data)); + emit setSql(sqlLevel); + break; + } + case cmdSetIFShift: + { + unsigned char IFShiftLevel = (*std::static_pointer_cast(data)); + emit setIFShift(IFShiftLevel); + break; + } + case cmdSetTPBFInner: + { + unsigned char innterLevel = (*std::static_pointer_cast(data)); + emit setTPBFInner(innterLevel); + break; + } + case cmdSetTPBFOuter: + { + unsigned char outerLevel = (*std::static_pointer_cast(data)); + emit setTPBFOuter(outerLevel); + break; + } + case cmdSetPTT: + { + bool pttrequest = (*std::static_pointer_cast(data)); + emit setPTT(pttrequest); + break; + } + case cmdSetATU: + { + bool atuOn = (*std::static_pointer_cast(data)); + emit setATU(atuOn); + break; + } + case cmdSetUTCOffset: + { + timekind u = (*std::static_pointer_cast(data)); + emit setUTCOffset(u); + break; + } + case cmdSetTime: + { + timekind t = (*std::static_pointer_cast(data)); + emit setTime(t); + break; + } + case cmdSetDate: + { + datekind d = (*std::static_pointer_cast(data)); + emit setDate(d); + break; + } + default: + doCmd(cmd); + break; + } + +} + + +void servermain::doCmd(cmds cmd) +{ + +} + + +void servermain::sendRadioCommandLoop() +{ + // Called by the periodicPollingTimer, see setInitialTiming() + + if(!(loopTickCounter % 2)) + { + // if ther's a command waiting, run it. + if(!delayedCmdQue.empty()) + { + commandtype cmddata = delayedCmdQue.front(); + delayedCmdQue.pop_front(); + doCmd(cmddata); + } else if(!(loopTickCounter % 10)) + { + // pick from useful queries to make now and then + if(haveRigCaps && !slowPollCmdQueue.empty()) + { + + int nCmds = slowPollCmdQueue.size(); + cmds sCmd = slowPollCmdQueue[(slowCmdNum++)%nCmds]; + doCmd(sCmd); + } + } + } else { + // odd-number ticks: + // s-meter or other metering + if(haveRigCaps && !periodicCmdQueue.empty()) + { + int nCmds = periodicCmdQueue.size(); + cmds pcmd = periodicCmdQueue[ (pCmdNum++)%nCmds ]; + doCmd(pcmd); + } + } + loopTickCounter++; +} + +void servermain::issueDelayedCommand(cmds cmd) +{ + // Append to end of command queue + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = NULL; + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueDelayedCommandPriority(cmds cmd) +{ + // Places the new command at the top of the queue + // Use only when needed. + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = NULL; + delayedCmdQue.push_front(cmddata); +} + +void servermain::issueDelayedCommandUnique(cmds cmd) +{ + // Use this function to insert commands where + // multiple (redundant) commands don't make sense. + + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = NULL; + + // The following is both expensive and not that great, + // since it does not check if the arguments are the same. + bool found = false; + for(unsigned int i=0; i < delayedCmdQue.size(); i++) + { + if(delayedCmdQue.at(i).cmd == cmd) + { + found = true; + break; + } + } + + if(!found) + { + delayedCmdQue.push_front(cmddata); + } + +// if( std::find(delayedCmdQue.begin(), delayedCmdQue.end(), cmddata ) == delayedCmdQue.end()) +// { +// delayedCmdQue.push_front(cmddata); +// } + +} + +void servermain::issueCmd(cmds cmd, mode_info m) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new mode_info(m)); + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueCmd(cmds cmd, freqt f) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new freqt(f)); + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueCmd(cmds cmd, timekind t) +{ + qDebug(logSystem()) << "Issuing timekind command with data: " << t.hours << " hours, " << t.minutes << " minutes, " << t.isMinus << " isMinus"; + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new timekind(t)); + delayedCmdQue.push_front(cmddata); +} + +void servermain::issueCmd(cmds cmd, datekind d) +{ + qDebug(logSystem()) << "Issuing datekind command with data: " << d.day << " day, " << d.month << " month, " << d.year << " year."; + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new datekind(d)); + delayedCmdQue.push_front(cmddata); +} + +void servermain::issueCmd(cmds cmd, int i) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new int(i)); + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueCmd(cmds cmd, char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new char(c)); + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueCmd(cmds cmd, bool b) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new bool(b)); + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueCmd(cmds cmd, unsigned char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new unsigned char(c)); + delayedCmdQue.push_back(cmddata); +} + +void servermain::issueCmdUniquePriority(cmds cmd, bool b) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new bool(b)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void servermain::issueCmdUniquePriority(cmds cmd, unsigned char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new unsigned char(c)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void servermain::issueCmdUniquePriority(cmds cmd, char c) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new char(c)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void servermain::issueCmdUniquePriority(cmds cmd, freqt f) +{ + commandtype cmddata; + cmddata.cmd = cmd; + cmddata.data = std::shared_ptr(new freqt(f)); + delayedCmdQue.push_front(cmddata); + removeSimilarCommand(cmd); +} + +void servermain::removeSimilarCommand(cmds cmd) +{ + // pop anything out that is of the same kind of command: + // pop anything out that is of the same kind of command: + // Start at 1 since we put one in at zero that we want to keep. + for(unsigned int i=1; i < delayedCmdQue.size(); i++) + { + if(delayedCmdQue.at(i).cmd == cmd) + { + //delayedCmdQue[i].cmd = cmdNone; + delayedCmdQue.erase(delayedCmdQue.begin()+i); + // i -= 1; + } + } +} + +void servermain::receiveRigID(rigCapabilities rigCaps) +{ + // Note: We intentionally request rigID several times + // because without rigID, we can't do anything with the waterfall. + if(haveRigCaps) + { + return; + } else { + + qDebug(logSystem()) << "Rig name: " << rigCaps.modelName; + qDebug(logSystem()) << "Has LAN capabilities: " << rigCaps.hasLan; + qDebug(logSystem()) << "Rig ID received into servermain: spectLenMax: " << rigCaps.spectLenMax; + qDebug(logSystem()) << "Rig ID received into servermain: spectAmpMax: " << rigCaps.spectAmpMax; + qDebug(logSystem()) << "Rig ID received into servermain: spectSeqMax: " << rigCaps.spectSeqMax; + qDebug(logSystem()) << "Rig ID received into servermain: hasSpectrum: " << rigCaps.hasSpectrum; + + this->rigCaps = rigCaps; + this->spectWidth = rigCaps.spectLenMax; // used once haveRigCaps is true. + haveRigCaps = true; + // Added so that server receives rig capabilities. + emit sendRigCaps(rigCaps); + + } +} + +void servermain::initPeriodicCommands() +{ + // This function places periodic polling commands into a queue. + // The commands are run using a timer, + // and the timer is started by the delayed command cmdStartPeriodicTimer. + + insertPeriodicCommand(cmdGetTxRxMeter, 128); + + insertSlowPeriodicCommand(cmdGetFreq, 128); + insertSlowPeriodicCommand(cmdGetMode, 128); + if(rigCaps.hasTransmit) + insertSlowPeriodicCommand(cmdGetPTT, 128); + insertSlowPeriodicCommand(cmdGetTxPower, 128); + insertSlowPeriodicCommand(cmdGetRxGain, 128); + if(rigCaps.hasAttenuator) + insertSlowPeriodicCommand(cmdGetAttenuator, 128); + if(rigCaps.hasTransmit) + insertSlowPeriodicCommand(cmdGetPTT, 128); + if(rigCaps.hasPreamp) + insertSlowPeriodicCommand(cmdGetPreamp, 128); + if (rigCaps.hasRXAntenna) { + insertSlowPeriodicCommand(cmdGetAntenna, 128); + } + insertSlowPeriodicCommand(cmdGetDuplexMode, 128); +} + +void servermain::insertPeriodicCommand(cmds cmd, unsigned char priority) +{ + // TODO: meaningful priority + // These commands get run at the fastest pace possible + // Typically just metering. + if(priority < 10) + { + periodicCmdQueue.push_front(cmd); + } else { + periodicCmdQueue.push_back(cmd); + } +} + +void servermain::insertPeriodicCommandUnique(cmds cmd) +{ + // Use this function to insert a non-duplicate command + // into the fast periodic polling queue, typically + // meter commands where high refresh rates are desirable. + + removePeriodicCommand(cmd); + periodicCmdQueue.push_front(cmd); +} + +void servermain::removePeriodicCommand(cmds cmd) +{ + while(true) + { + auto it = std::find(this->periodicCmdQueue.begin(), this->periodicCmdQueue.end(), cmd); + if(it != periodicCmdQueue.end()) + { + periodicCmdQueue.erase(it); + } else { + break; + } + } +} + + +void servermain::insertSlowPeriodicCommand(cmds cmd, unsigned char priority) +{ + // TODO: meaningful priority + // These commands are run every 20 "ticks" of the primary radio command loop + // Basically 20 times less often than the standard peridic command + if(priority < 10) + { + slowPollCmdQueue.push_front(cmd); + } else { + slowPollCmdQueue.push_back(cmd); + } +} + +void servermain::receiveFreq(freqt freqStruct) +{ + + qint64 tnow_ms = QDateTime::currentMSecsSinceEpoch(); + if(tnow_ms - lastFreqCmdTime_ms > delayedCommand->interval() * 2) + { + freq = freqStruct; + } else { + qDebug(logSystem()) << "Rejecting stale frequency: " << freqStruct.Hz << " Hz, delta time ms = " << tnow_ms - lastFreqCmdTime_ms\ + << ", tnow_ms " << tnow_ms << ", last: " << lastFreqCmdTime_ms; + } +} + +void servermain::receivePTTstatus(bool pttOn) +{ + // This is the only place where amTransmitting and the transmit button text should be changed: + //qInfo(logSystem()) << "PTT status: " << pttOn; + amTransmitting = pttOn; +} + +void servermain::changeTxBtn() +{ +} + + +void servermain::receiveDataModeStatus(bool dataEnabled) +{ +} + +void servermain::checkFreqSel() +{ + if(freqTextSelected) + { + freqTextSelected = false; + } +} + +void servermain::changeMode(mode_kind mode) +{ + bool dataOn = false; + if(((unsigned char) mode >> 4) == 0x08) + { + dataOn = true; + mode = (mode_kind)((int)mode & 0x0f); + } + + changeMode(mode, dataOn); +} + +void servermain::changeMode(mode_kind mode, bool dataOn) +{ +} + +void servermain::receiveBandStackReg(freqt freqGo, char mode, char filter, bool dataOn) +{ + // read the band stack and apply by sending out commands + + qInfo(logSystem()) << __func__ << "BSR received into main: Freq: " << freqGo.Hz << ", mode: " << (unsigned int)mode << ", filter: " << (unsigned int)filter << ", data mode: " << dataOn; + //emit setFrequency(0,freq); + issueCmd(cmdSetFreq, freqGo); + setModeVal = (unsigned char) mode; + setFilterVal = (unsigned char) filter; + + issueDelayedCommand(cmdSetModeFilter); + freq = freqGo; + + if(dataOn) + { + issueDelayedCommand(cmdSetDataModeOn); + } else { + issueDelayedCommand(cmdSetDataModeOff); + } + //issueDelayedCommand(cmdGetFreq); + //issueDelayedCommand(cmdGetMode); + +} + +void servermain::bandStackBtnClick() +{ +} + +void servermain::receiveRfGain(unsigned char level) +{ +} + +void servermain::receiveAfGain(unsigned char level) +{ +} + +void servermain::receiveSql(unsigned char level) +{ +} + +void servermain::receiveIFShift(unsigned char level) +{ +} + +void servermain::receiveTBPFInner(unsigned char level) +{ +} + +void servermain::receiveTBPFOuter(unsigned char level) +{ +} + +void servermain::setRadioTimeDatePrep() +{ + if(!waitingToSetTimeDate) + { + // 1: Find the current time and date + QDateTime now; + now = QDateTime::currentDateTime(); + now.setTime(QTime::currentTime()); + + int second = now.time().second(); + + // 2: Find how many mseconds until next minute + int msecdelay = QTime::currentTime().msecsTo( QTime::currentTime().addSecs(60-second) ); + + // 3: Compute time and date at one minute later + QDateTime setpoint = now.addMSecs(msecdelay); // at HMS or posibly HMS + some ms. Never under though. + + // 4: Prepare data structs for the time at one minute later + timesetpoint.hours = (unsigned char)setpoint.time().hour(); + timesetpoint.minutes = (unsigned char)setpoint.time().minute(); + datesetpoint.day = (unsigned char)setpoint.date().day(); + datesetpoint.month = (unsigned char)setpoint.date().month(); + datesetpoint.year = (uint16_t)setpoint.date().year(); + unsigned int utcOffsetSeconds = (unsigned int)abs(setpoint.offsetFromUtc()); + bool isMinus = setpoint.offsetFromUtc() < 0; + utcsetting.hours = utcOffsetSeconds / 60 / 60; + utcsetting.minutes = (utcOffsetSeconds - (utcsetting.hours*60*60) ) / 60; + utcsetting.isMinus = isMinus; + + timeSync->setInterval(msecdelay); + timeSync->setSingleShot(true); + + // 5: start one-shot timer for the delta computed in #2. + timeSync->start(); + waitingToSetTimeDate = true; + } +} + +void servermain::setRadioTimeDateSend() +{ + // Issue priority commands for UTC offset, date, and time + // UTC offset must come first, otherwise the radio may "help" and correct for any changes. + + issueCmd(cmdSetTime, timesetpoint); + issueCmd(cmdSetDate, datesetpoint); + issueCmd(cmdSetUTCOffset, utcsetting); + waitingToSetTimeDate = false; +} + + +void servermain::receiveTxPower(unsigned char power) +{ +} + +void servermain::receiveMicGain(unsigned char gain) +{ + processModLevel(inputMic, gain); +} + +void servermain::processModLevel(rigInput source, unsigned char level) +{ + rigInput currentIn; + if(usingDataMode) + { + currentIn = currentModDataSrc; + } else { + currentIn = currentModSrc; + } + + switch(source) + { + case inputMic: + micGain = level; + break; + case inputACC: + accGain = level; + break; + + case inputACCA: + accAGain = level; + break; + + case inputACCB: + accBGain = level; + break; + + case inputUSB: + usbGain = level; + break; + + case inputLAN: + lanGain = level; + break; + + default: + break; + } + +} + +void servermain::receiveModInput(rigInput input, bool dataOn) +{ +} + +void servermain::receiveACCGain(unsigned char level, unsigned char ab) +{ + if(ab==1) + { + processModLevel(inputACCB, level); + } else { + if(rigCaps.model == model7850) + { + processModLevel(inputACCA, level); + } else { + processModLevel(inputACC, level); + } + } +} + +void servermain::receiveUSBGain(unsigned char level) +{ + processModLevel(inputUSB, level); +} + +void servermain::receiveLANGain(unsigned char level) +{ + processModLevel(inputLAN, level); +} + +void servermain::receiveMeter(meterKind inMeter, unsigned char level) +{ + +} + +void servermain::receiveCompLevel(unsigned char compLevel) +{ + (void)compLevel; +} + +void servermain::receiveMonitorGain(unsigned char monitorGain) +{ + (void)monitorGain; +} + +void servermain::receiveVoxGain(unsigned char voxGain) +{ + (void)voxGain; +} + +void servermain::receiveAntiVoxGain(unsigned char antiVoxGain) +{ + (void)antiVoxGain; +} + + +void servermain::receiveSpectrumRefLevel(int level) +{ +} + +void servermain::changeModLabelAndSlider(rigInput source) +{ + changeModLabel(source, true); +} + +void servermain::changeModLabel(rigInput input) +{ + changeModLabel(input, false); +} + +void servermain::changeModLabel(rigInput input, bool updateLevel) +{ +} + +void servermain::processChangingCurrentModLevel(unsigned char level) +{ + // slider moved, so find the current mod and issue the level set command. + issueCmd(cmdSetModLevel, level); +} +void servermain::receivePreamp(unsigned char pre) +{ +} + +void servermain::receiveAttenuator(unsigned char att) +{ +} + +void servermain::receiveAntennaSel(unsigned char ant, bool rx) +{ +} + + +void servermain::calculateTimingParameters() +{ + // Function for calculating polling parameters. + // Requires that we know the "baud rate" of the actual + // radio connection. + + // baud on the serial port reflects the actual rig connection, + // even if a client-server connection is being used. + // Computed time for a 10 byte message, with a safety factor of 2. + + if (prefs.serialPortBaud == 0) + { + prefs.serialPortBaud = 9600; + qInfo(logSystem()) << "WARNING: baud rate received was zero. Assuming 9600 baud, performance may suffer."; + } + + unsigned int usPerByte = 9600*1000 / prefs.serialPortBaud; + unsigned int msMinTiming=usPerByte * 10*2/1000; + if(msMinTiming < 25) + msMinTiming = 25; + + if(haveRigCaps && rigCaps.hasFDcomms) + { + delayedCommand->setInterval( msMinTiming); // 20 byte message + } else { + delayedCommand->setInterval( msMinTiming * 3); // 20 byte message + } + + + qInfo(logSystem()) << "Delay command interval timing: " << delayedCommand->interval() << "ms"; + + // Normal: + delayedCmdIntervalLAN_ms = delayedCommand->interval(); + delayedCmdIntervalSerial_ms = delayedCommand->interval(); + + // startup initial state: + delayedCmdStartupInterval_ms = delayedCommand->interval() * 3; +} + +void servermain::receiveBaudRate(quint32 baud) +{ + qInfo() << "Received serial port baud rate from remote server:" << baud; + prefs.serialPortBaud = baud; + calculateTimingParameters(); +} + +void servermain::powerRigOn() +{ + emit sendPowerOn(); + + delayedCommand->setInterval(3000); // 3 seconds + issueDelayedCommand(cmdQueNormalSpeed); + issueDelayedCommand(cmdStartRegularPolling); // s-meter, etc + delayedCommand->start(); +} + +void servermain::powerRigOff() +{ + delayedCommand->stop(); + delayedCmdQue.clear(); + + emit sendPowerOff(); +} + + +void servermain::receiveRITStatus(bool ritEnabled) +{ +} + +void servermain::receiveRITValue(int ritValHz) +{ +} + +servermain::cmds servermain::meterKindToMeterCommand(meterKind m) +{ + cmds c; + switch(m) + { + case meterNone: + c = cmdNone; + break; + case meterS: + c = cmdGetSMeter; + break; + case meterCenter: + c = cmdGetCenterMeter; + break; + case meterPower: + c = cmdGetPowerMeter; + break; + case meterSWR: + c = cmdGetSWRMeter; + break; + case meterALC: + c = cmdGetALCMeter; + break; + case meterComp: + c = cmdGetCompMeter; + break; + case meterCurrent: + c = cmdGetIdMeter; + break; + case meterVoltage: + c = cmdGetVdMeter; + break; + default: + c = cmdNone; + break; + } + + return c; +} + + +void servermain::handleCtrlC(int sig) { + if (sig == 2) { + QCoreApplication::quit(); + //exit(EXIT_FAILURE); + } +} diff --git a/servermain.h b/servermain.h new file mode 100644 index 0000000..4d79004 --- /dev/null +++ b/servermain.h @@ -0,0 +1,510 @@ +#ifndef WFMAIN_H +#define WFMAIN_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "logcategories.h" +#include "commhandler.h" +#include "rigcommander.h" +#include "rigstate.h" +#include "freqmemory.h" +#include "rigidentities.h" +#include "repeaterattributes.h" + +#include "udpserver.h" +#include "rigctld.h" +#include "signal.h" + +#include + +#include +#include + +namespace Ui { +class wfmain; +} + +class servermain : public QObject +{ + Q_OBJECT + +public: + servermain(const QString serialPortCL, const QString hostCL, const QString settingsFile); + QString serialPortCL; + QString hostCL; + ~servermain(); + +signals: + // Basic to rig: + void setCIVAddr(unsigned char newRigCIVAddr); + void setRigID(unsigned char rigID); + void setRTSforPTT(bool enabled); + + // Power + void sendPowerOn(); + void sendPowerOff(); + + // Frequency, mode, band: + void getFrequency(); + void setFrequency(unsigned char vfo, freqt freq); + void getMode(); + void setMode(unsigned char modeIndex, unsigned char modeFilter); + void setMode(mode_info); + void setDataMode(bool dataOn, unsigned char filter); + void getDataMode(); + void getModInput(bool dataOn); + void setModInput(rigInput input, bool dataOn); + void getBandStackReg(char band, char regCode); + void getDebug(); + void getRitEnabled(); + void getRitValue(); + void setRitValue(int ritValue); + void setRitEnable(bool ritEnabled); + + // Repeater: + void getDuplexMode(); + void getTone(); + void getTSQL(); + void getDTCS(); + void getRptAccessMode(); + + // Level get: + void getLevels(); // get all levels + void getRfGain(); + void getAfGain(); + void getSql(); + void getIfShift(); + void getTPBFInner(); + void getTPBFOuter(); + void getTxPower(); + void getMicGain(); + void getSpectrumRefLevel(); + void getModInputLevel(rigInput input); + + // Level set: + void setRfGain(unsigned char level); + void setAfGain(unsigned char level); + void setSql(unsigned char level); + void setIFShift(unsigned char level); + void setTPBFInner(unsigned char level); + void setTPBFOuter(unsigned char level); + + void setIFShiftWindow(unsigned char level); + void setTPBFInnerWindow(unsigned char level); + void setTPBFOuterWindow(unsigned char level); + void setMicGain(unsigned char); + void setCompLevel(unsigned char); + void setTxPower(unsigned char); + void setMonitorLevel(unsigned char); + void setVoxGain(unsigned char); + void setAntiVoxGain(unsigned char); + void setSpectrumRefLevel(int); + + void setModLevel(rigInput input, unsigned char level); + void setACCGain(unsigned char level); + void setACCAGain(unsigned char level); + void setACCBGain(unsigned char level); + void setUSBGain(unsigned char level); + void setLANGain(unsigned char level); + + void getMeters(meterKind meter); + + + // PTT, ATU, ATT, Antenna, Preamp: + void getPTT(); + void setPTT(bool pttOn); + void getAttenuator(); + void getPreamp(); + void getAntenna(); + void setAttenuator(unsigned char att); + void setPreamp(unsigned char pre); + void setAntenna(unsigned char ant, bool rx); + void startATU(); + void setATU(bool atuEnabled); + void getATUStatus(); + + // Time and date: + void setTime(timekind t); + void setDate(datekind d); + void setUTCOffset(timekind t); + + void getRigID(); // this is the model of the rig + void getRigCIV(); // get the rig's CIV addr + void spectOutputEnable(); + void spectOutputDisable(); + void scopeDisplayEnable(); + void scopeDisplayDisable(); + void setScopeMode(spectrumMode spectMode); + void setScopeSpan(char span); + void setScopeEdge(char edge); + void setScopeFixedEdge(double startFreq, double endFreq, unsigned char edgeNumber); + void getScopeMode(); + void getScopeEdge(); + void getScopeSpan(); + void sayFrequency(); + void sayMode(); + void sayAll(); + void sendCommSetup(unsigned char rigCivAddr, QString rigSerialPort, quint32 rigBaudRate,QString vsp); + void sendCommSetup(unsigned char rigCivAddr, udpPreferences prefs, audioSetup rxSetup, audioSetup txSetup, QString vsp); + void sendCloseComm(); + void sendChangeLatency(quint16 latency); + void initServer(); + void sendRigCaps(rigCapabilities caps); + void requestRigState(); + void stateUpdated(); + +private slots: + + void receiveCommReady(); + void receiveFreq(freqt); + void receivePTTstatus(bool pttOn); + void receiveDataModeStatus(bool dataOn); + void receiveBandStackReg(freqt f, char mode, char filter, bool dataOn); // freq, mode, (filter,) datamode + void receiveRITStatus(bool ritEnabled); + void receiveRITValue(int ritValHz); + void receiveModInput(rigInput input, bool dataOn); + //void receiveDuplexMode(duplexMode dm); + + + + // Levels: + void receiveRfGain(unsigned char level); + void receiveAfGain(unsigned char level); + void receiveSql(unsigned char level); + void receiveIFShift(unsigned char level); + void receiveTBPFInner(unsigned char level); + void receiveTBPFOuter(unsigned char level); + // 'change' from data in transceiver controls window: + void receiveTxPower(unsigned char power); + void receiveMicGain(unsigned char gain); + void receiveCompLevel(unsigned char compLevel); + void receiveMonitorGain(unsigned char monitorGain); + void receiveVoxGain(unsigned char voxGain); + void receiveAntiVoxGain(unsigned char antiVoxGain); + void receiveSpectrumRefLevel(int level); + void receiveACCGain(unsigned char level, unsigned char ab); + void receiveUSBGain(unsigned char level); + void receiveLANGain(unsigned char level); + + // Meters: + void receiveMeter(meterKind meter, unsigned char level); +// void receiveSMeter(unsigned char level); +// void receivePowerMeter(unsigned char level); +// void receiveALCMeter(unsigned char level); +// void receiveCompMeter(unsigned char level); + + + void receivePreamp(unsigned char pre); + void receiveAttenuator(unsigned char att); + void receiveAntennaSel(unsigned char ant, bool rx); + void receiveRigID(rigCapabilities rigCaps); + void receiveFoundRigID(rigCapabilities rigCaps); + void receiveSerialPortError(QString port, QString errorText); + void sendRadioCommandLoop(); + void receiveBaudRate(quint32 baudrate); + + void setRadioTimeDateSend(); + + +private: + Ui::wfmain *ui; + void closeEvent(QCloseEvent *event); + QSettings *settings=Q_NULLPTR; + void loadSettings(); + + void getInitialRigState(); + + void openRig(); + void powerRigOff(); + void powerRigOn(); + QStringList portList; + QString serialPortRig; + + rigCommander * rig=Q_NULLPTR; + QThread* rigThread = Q_NULLPTR; + QTimer * delayedCommand; + QTimer * pttTimer; + uint16_t loopTickCounter; + uint16_t slowCmdNum; + + void makeRig(); + void rigConnections(); + void removeRig(); + void findSerialPort(); + + void setServerToPrefs(); + void setInitialTiming(); + void getSettingsFilePath(QString settingsFile); + + QStringList modes; + int currentModeIndex; + QStringList spans; + QStringList edges; + QStringList commPorts; + + quint16 spectWidth; + quint16 wfLength; + bool spectrumDrawLock; + + QByteArray spectrumPeaks; + + QVector wfimage; + unsigned int wfLengthMax; + + bool onFullscreen; + bool drawPeaks; + bool freqTextSelected; + void checkFreqSel(); + + double oldLowerFreq; + double oldUpperFreq; + freqt freq; + float tsKnobMHz; + + unsigned char setModeVal=0; + unsigned char setFilterVal=0; + + enum cmds {cmdNone, cmdGetRigID, cmdGetRigCIV, cmdGetFreq, cmdSetFreq, cmdGetMode, cmdSetMode, + cmdGetDataMode, cmdSetModeFilter, cmdSetDataModeOn, cmdSetDataModeOff, cmdGetRitEnabled, cmdGetRitValue, + cmdSpecOn, cmdSpecOff, cmdDispEnable, cmdDispDisable, cmdGetRxGain, cmdSetRxRfGain, cmdGetAfGain, cmdSetAfGain, + cmdGetSql, cmdSetSql, cmdGetIFShift, cmdSetIFShift, cmdGetTPBFInner, cmdSetTPBFInner, + cmdGetTPBFOuter, cmdSetTPBFOuter, cmdGetATUStatus, + cmdSetATU, cmdStartATU, cmdGetSpectrumMode, + cmdGetSpectrumSpan, cmdScopeCenterMode, cmdScopeFixedMode, cmdGetPTT, cmdSetPTT, + cmdGetTxPower, cmdSetTxPower, cmdGetMicGain, cmdSetMicGain, cmdSetModLevel, + cmdGetSpectrumRefLevel, cmdGetDuplexMode, cmdGetModInput, cmdGetModDataInput, + cmdGetCurrentModLevel, cmdStartRegularPolling, cmdStopRegularPolling, cmdQueNormalSpeed, + cmdGetVdMeter, cmdGetIdMeter, cmdGetSMeter, cmdGetCenterMeter, cmdGetPowerMeter, + cmdGetSWRMeter, cmdGetALCMeter, cmdGetCompMeter, cmdGetTxRxMeter, + cmdGetTone, cmdGetTSQL, cmdGetDTCS, cmdGetRptAccessMode, cmdGetPreamp, cmdGetAttenuator, cmdGetAntenna, + cmdSetTime, cmdSetDate, cmdSetUTCOffset}; + + struct commandtype { + cmds cmd; + std::shared_ptr data; + }; + + std::deque delayedCmdQue; // rapid que for commands to the radio + std::deque periodicCmdQueue; // rapid que for metering + std::deque slowPollCmdQueue; // slow, regular checking for UI sync + void doCmd(cmds cmd); + void doCmd(commandtype cmddata); + + void issueCmd(cmds cmd, freqt f); + void issueCmd(cmds cmd, mode_info m); + void issueCmd(cmds cmd, timekind t); + void issueCmd(cmds cmd, datekind d); + void issueCmd(cmds cmd, int i); + void issueCmd(cmds cmd, unsigned char c); + void issueCmd(cmds cmd, char c); + void issueCmd(cmds cmd, bool b); + + // These commands pop_front and remove similar commands: + void issueCmdUniquePriority(cmds cmd, bool b); + void issueCmdUniquePriority(cmds cmd, unsigned char c); + void issueCmdUniquePriority(cmds cmd, char c); + void issueCmdUniquePriority(cmds cmd, freqt f); + + void removeSimilarCommand(cmds cmd); + + qint64 lastFreqCmdTime_ms; + + int pCmdNum = 0; + int delayedCmdIntervalLAN_ms = 100; + int delayedCmdIntervalSerial_ms = 100; + int delayedCmdStartupInterval_ms = 100; + bool runPeriodicCommands; + bool usingLAN = false; + + // Radio time sync: + QTimer *timeSync; + bool waitingToSetTimeDate; + void setRadioTimeDatePrep(); + timekind timesetpoint; + timekind utcsetting; + datekind datesetpoint; + + freqMemory mem; + struct colors { + QColor Dark_PlotBackground; + QColor Dark_PlotAxisPen; + QColor Dark_PlotLegendTextColor; + QColor Dark_PlotLegendBorderPen; + QColor Dark_PlotLegendBrush; + QColor Dark_PlotTickLabel; + QColor Dark_PlotBasePen; + QColor Dark_PlotTickPen; + QColor Dark_PeakPlotLine; + QColor Dark_TuningLine; + + QColor Light_PlotBackground; + QColor Light_PlotAxisPen; + QColor Light_PlotLegendTextColor; + QColor Light_PlotLegendBorderPen; + QColor Light_PlotLegendBrush; + QColor Light_PlotTickLabel; + QColor Light_PlotBasePen; + QColor Light_PlotTickPen; + QColor Light_PeakPlotLine; + QColor Light_TuningLine; + + } colorScheme; + + struct preferences { + bool useFullScreen; + bool useDarkMode; + bool useSystemTheme; + bool drawPeaks; + bool wfAntiAlias; + bool wfInterpolate; + QString stylesheetPath; + unsigned char radioCIVAddr; + bool CIVisRadioModel; + bool forceRTSasPTT; + QString serialPortRadio; + quint32 serialPortBaud; + bool enablePTT; + bool niceTS; + bool enableLAN; + bool enableRigCtlD; + quint16 rigCtlPort; + colors colorScheme; + QString virtualSerialPort; + unsigned char localAFgain; + unsigned int wflength; + int wftheme; + bool confirmExit; + bool confirmPowerOff; + meterKind meter2Type; + // plot scheme + } prefs; + + preferences defPrefs; + udpPreferences udpPrefs; + udpPreferences udpDefPrefs; + + // Configuration for audio output and input. + audioSetup rxSetup; + audioSetup txSetup; + + audioSetup serverRxSetup; + audioSetup serverTxSetup; + + colors defaultColors; + + void setDefaultColors(); // populate with default values + void useColors(); // set the plot up + void setDefPrefs(); // populate default values to default prefs + void setTuningSteps(); + + quint64 roundFrequency(quint64 frequency, unsigned int tsHz); + quint64 roundFrequencyWithStep(quint64 oldFreq, int steps,\ + unsigned int tsHz); + + void changeTxBtn(); + void issueDelayedCommand(cmds cmd); + void issueDelayedCommandPriority(cmds cmd); + void issueDelayedCommandUnique(cmds cmd); + + void processModLevel(rigInput source, unsigned char level); + + void processChangingCurrentModLevel(unsigned char level); + + void changeModLabel(rigInput source); + void changeModLabel(rigInput source, bool updateLevel); + + void changeModLabelAndSlider(rigInput source); + + // Fast command queue: + void initPeriodicCommands(); + void insertPeriodicCommand(cmds cmd, unsigned char priority); + void insertPeriodicCommandUnique(cmds cmd); + void removePeriodicCommand(cmds cmd); + + void insertSlowPeriodicCommand(cmds cmd, unsigned char priority); + void calculateTimingParameters(); + + void changeMode(mode_kind mode); + void changeMode(mode_kind mode, bool dataOn); + + cmds meterKindToMeterCommand(meterKind m); + + int oldFreqDialVal; + + rigCapabilities rigCaps; + rigInput currentModSrc = inputUnknown; + rigInput currentModDataSrc = inputUnknown; + mode_kind currentMode = modeUSB; + mode_info currentModeInfo; + + bool haveRigCaps; + bool amTransmitting; + bool usingDataMode = false; + + unsigned char micGain=0; + unsigned char accAGain=0; + unsigned char accBGain=0; + unsigned char accGain=0; + unsigned char usbGain=0; + unsigned char lanGain=0; + + + udpServer* udp = Q_NULLPTR; + rigCtlD* rigCtl = Q_NULLPTR; + QThread* serverThread = Q_NULLPTR; + + void bandStackBtnClick(); + bool waitingForBandStackRtn; + char bandStkBand; + char bandStkRegCode; + + bool freqLock; + + float tsPlus; + float tsPlusShift; + float tsPlusControl; + float tsPage; + float tsPageShift; + float tsWfScroll; + + unsigned int tsPlusHz; + unsigned int tsPlusShiftHz; + unsigned int tsPlusControlHz; + unsigned int tsPageHz; + unsigned int tsPageShiftHz; + unsigned int tsWfScrollHz; + unsigned int tsKnobHz; + + rigstate* rigState = Q_NULLPTR; + + SERVERCONFIG serverConfig; + + static void handleCtrlC(int sig); +}; + +Q_DECLARE_METATYPE(struct rigCapabilities) +Q_DECLARE_METATYPE(struct freqt) +Q_DECLARE_METATYPE(struct mode_info) +Q_DECLARE_METATYPE(struct udpPreferences) +Q_DECLARE_METATYPE(struct audioPacket) +Q_DECLARE_METATYPE(struct audioSetup) +Q_DECLARE_METATYPE(struct SERVERCONFIG) +Q_DECLARE_METATYPE(struct timekind) +Q_DECLARE_METATYPE(struct datekind) +Q_DECLARE_METATYPE(enum rigInput) +Q_DECLARE_METATYPE(enum meterKind) +Q_DECLARE_METATYPE(enum spectrumMode) +Q_DECLARE_METATYPE(rigstate*) + + +#endif // WFMAIN_H diff --git a/wfmain.h b/wfmain.h index 236af59..6a8bd71 100644 --- a/wfmain.h +++ b/wfmain.h @@ -1,3 +1,7 @@ +#ifdef WFSERVER +#include "servermain.h" +#else + #ifndef WFMAIN_H #define WFMAIN_H @@ -889,3 +893,4 @@ Q_DECLARE_METATYPE(rigstate*) #endif // WFMAIN_H +#endif \ No newline at end of file diff --git a/wfserver.pro b/wfserver.pro new file mode 100644 index 0000000..993c9cc --- /dev/null +++ b/wfserver.pro @@ -0,0 +1,158 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-05-26T16:57:32 +# +#------------------------------------------------- + +QT += core serialport network multimedia + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport + +TARGET = wfserver +TEMPLATE = app + +CONFIG += console + +DEFINES += WFVIEW_VERSION=\\\"1.2d\\\" + +DEFINES += WFSERVER + +CONFIG(debug, release|debug) { +# For Debug builds only: +QMAKE_CXXFLAGS += -faligned-new + +} else { +# For Release builds only: +linux:QMAKE_CXXFLAGS += -s +QMAKE_CXXFLAGS += -fvisibility=hidden +QMAKE_CXXFLAGS += -fvisibility-inlines-hidden +QMAKE_CXXFLAGS += -faligned-new +linux:QMAKE_LFLAGS += -O2 -s +} + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which as been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS +DEFINES += QCUSTOMPLOT_COMPILE_LIBRARY + + +# These defines are used for the resampler +equals(QT_ARCH, i386): DEFINES += USE_SSE +equals(QT_ARCH, i386): DEFINES += USE_SSE2 +equals(QT_ARCH, arm): DEFINES += USE_NEON +DEFINES += OUTSIDE_SPEEX +DEFINES += RANDOM_PREFIX=wf + +isEmpty(PREFIX) { + PREFIX = /usr/local +} + +DEFINES += PREFIX=\\\"$$PREFIX\\\" + +# Choose audio system, uses QTMultimedia if both are commented out. +# DEFINES += RTAUDIO +# DEFINES += PORTAUDIO + +contains(DEFINES, RTAUDIO) { + # RTAudio defines + win32:DEFINES += __WINDOWS_WASAPI__ + #win32:DEFINES += __WINDOWS_DS__ # Requires DirectSound libraries + linux:DEFINES += __LINUX_ALSA__ + #linux:DEFINES += __LINUX_OSS__ + #linux:DEFINES += __LINUX_PULSE__ + macx:DEFINES += __MACOSX_CORE__ + win32:SOURCES += ../rtaudio/RTAudio.cpp + win32:HEADERS += ../rtaudio/RTAUdio.h + !linux:INCLUDEPATH += ../rtaudio + linux:LIBS += -lpulse -lpulse-simple -lrtaudio -lpthread +} + +contains(DEFINES, PORTAUDIO) { + CONFIG(debug, release|debug) { + win32:LIBS += -L../portaudio/msvc/Win32/Debug/ -lportaudio_x86 + } else { + win32:LIBS += -L../portaudio/msvc/Win32/Release/ -lportaudio_x86 + } + win32:INCLUDEPATH += ../portaudio/include + !win32:LIBS += -lportaudio +} + +macx:INCLUDEPATH += /usr/local/include /opt/local/include +macx:LIBS += -L/usr/local/lib -L/opt/local/lib + +macx:ICON = ../wfview/resources/wfview.icns +win32:RC_ICONS = ../wfview/resources/wfview.ico +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.13 +QMAKE_TARGET_BUNDLE_PREFIX = org.wfview +MY_ENTITLEMENTS.name = CODE_SIGN_ENTITLEMENTS +MY_ENTITLEMENTS.value = ../wfview/resources/wfview.entitlements +QMAKE_MAC_XCODE_SETTINGS += MY_ENTITLEMENTS +QMAKE_INFO_PLIST = ../wfview/resources/Info.plist + +!win32:DEFINES += HOST=\\\"`hostname`\\\" UNAME=\\\"`whoami`\\\" + +!win32:DEFINES += GITSHORT="\\\"$(shell git -C $$PWD rev-parse --short HEAD)\\\"" +win32:DEFINES += GITSHORT=\\\"$$system(git -C $$PWD rev-parse --short HEAD)\\\" + +win32:DEFINES += HOST=\\\"wfview.org\\\" +win32:DEFINES += UNAME=\\\"build\\\" + + +RESOURCES += qdarkstyle/style.qrc \ + resources/resources.qrc + +unix:target.path = $$PREFIX/bin +INSTALLS += target + +# Do not do this, it will hang on start: +# CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT + +CONFIG(debug, release|debug) { + win32:LIBS += -L../opus/win32/VS2015/Win32/Debug/ -lopus +} else { + win32:LIBS += -L../opus/win32/VS2015/Win32/Release/ -lopus +} + +linux:LIBS += -L./ -l$$QCPLIB -lopus +macx:LIBS += -framework CoreAudio -framework CoreFoundation -lpthread -lopus + +!linux:INCLUDEPATH += ../opus/include + +INCLUDEPATH += resampler + +SOURCES += main.cpp\ + servermain.cpp \ + commhandler.cpp \ + rigcommander.cpp \ + freqmemory.cpp \ + rigidentities.cpp \ + udphandler.cpp \ + logcategories.cpp \ + audiohandler.cpp \ + udpserver.cpp \ + pttyhandler.cpp \ + resampler/resample.c \ + rigctld.cpp \ + ring/ring.cpp + +HEADERS += servermain.h \ + commhandler.h \ + rigcommander.h \ + freqmemory.h \ + rigidentities.h \ + udphandler.h \ + logcategories.h \ + audiohandler.h \ + udpserver.h \ + packettypes.h \ + pttyhandler.h \ + resampler/speex_resampler.h \ + resampler/arch.h \ + resampler/resample_sse.h \ + repeaterattributes.h \ + rigctld.h \ + ulaw.h \ + ring/ring.h \ + audiotaper.h diff --git a/wfserver.vcxproj b/wfserver.vcxproj new file mode 100644 index 0000000..925094b --- /dev/null +++ b/wfserver.vcxproj @@ -0,0 +1,313 @@ + + + + + Release + Win32 + + + Debug + Win32 + + + + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56} + wfserver + QtVS_v304 + 10.0.19041.0 + 10.0.19041.0 + $(MSBuildProjectDirectory)\QtMsBuild + + + + v142 + release\ + false + NotSet + Application + release\ + wfserver + + + v142 + debug\ + false + NotSet + Application + debug\ + wfserver + + + + + + + + + + + + + + + + + + debug\ + debug\ + wfserver + true + + + release\ + release\ + wfserver + true + false + + + msvc2019 + core;network;gui;multimedia;widgets;serialport;printsupport + + + msvc2019 + core;network;gui;multimedia;widgets;serialport;printsupport + + + + + + + .;..\opus\include;resampler;release;/include;%(AdditionalIncludeDirectories) + -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) + release\ + false + None + 4577;4467;%(DisableSpecificWarnings) + Sync + release\ + MaxSpeed + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="28812be";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + false + + + MultiThreadedDLL + true + true + Level3 + true + + + ..\opus\win32\VS2015\Win32\Release\opus.lib;%(AdditionalDependencies) + ..\opus\win32\VS2015\Win32\Release;%(AdditionalLibraryDirectories) + "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) + true + false + true + false + true + $(OutDir)\wfserver.exe + true + Console + true + + + Unsigned + None + 0 + + + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"28812be\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + + + msvc + ./$(Configuration)/moc_predefs.h + Moc'ing %(Identity)... + output + $(Configuration) + moc_%(Filename).cpp + + + default + Rcc'ing %(Identity)... + $(Configuration) + qrc_%(Filename).cpp + + + + + .;..\opus\include;resampler;debug;/include;%(AdditionalIncludeDirectories) + -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions) + debug\ + false + ProgramDatabase + 4577;4467;%(DisableSpecificWarnings) + Sync + debug\ + Disabled + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="28812be";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + false + MultiThreadedDebugDLL + true + true + Level3 + true + + + ..\opus\win32\VS2015\Win32\Debug\opus.lib;%(AdditionalDependencies) + ..\opus\win32\VS2015\Win32\Debug;%(AdditionalLibraryDirectories) + "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions) + true + true + true + $(OutDir)\wfserver.exe + true + Console + true + + + Unsigned + None + 0 + + + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"28812be\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + + + msvc + ./$(Configuration)/moc_predefs.h + Moc'ing %(Identity)... + output + $(Configuration) + moc_%(Filename).cpp + + + default + Rcc'ing %(Identity)... + $(Configuration) + qrc_%(Filename).cpp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + true + $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) + cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -faligned-new -Zi -MDd -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >debug\moc_predefs.h + Generate moc_predefs.h + debug\moc_predefs.h;%(Outputs) + + + Document + $(QTDIR)\mkspecs\features\data\dummy.cpp;%(AdditionalInputs) + cl -Bx"$(QTDIR)\bin\qmake.exe" -nologo -Zc:wchar_t -FS -Zc:rvalueCast -Zc:inline -Zc:strictStrings -Zc:throwingNew -Zc:referenceBinding -Zc:__cplusplus -fvisibility=hidden -fvisibility-inlines-hidden -faligned-new -O2 -MD -W3 -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 -wd4577 -wd4467 -E $(QTDIR)\mkspecs\features\data\dummy.cpp 2>NUL >release\moc_predefs.h + Generate moc_predefs.h + release\moc_predefs.h;%(Outputs) + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + resources + resources + + + + + + style + style + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wfserver.vcxproj.filters b/wfserver.vcxproj.filters new file mode 100644 index 0000000..e2466f8 --- /dev/null +++ b/wfserver.vcxproj.filters @@ -0,0 +1,284 @@ + + + + + {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11} + cpp;c;cxx;moc;h;def;odl;idl;res; + + + {71ED8ED8-ACB9-4CE9-BBE1-E00B30144E11} + cpp;c;cxx;moc;h;def;odl;idl;res; + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} + qrc;* + false + + + {D9D6E242-F8AF-46E4-B9FD-80ECBC20BA3E} + qrc;* + false + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Generated Files + + + Generated Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + Resource Files + + + + + + \ No newline at end of file diff --git a/wfserver.vcxproj.user b/wfserver.vcxproj.user new file mode 100644 index 0000000..65dc681 --- /dev/null +++ b/wfserver.vcxproj.user @@ -0,0 +1,10 @@ + + + + + 2022-01-17T12:12:10.6444561Z + + + 2022-01-17T12:12:12.8619428Z + + \ No newline at end of file diff --git a/wfserver_resource.rc b/wfserver_resource.rc new file mode 100644 index 0000000..d437633 --- /dev/null +++ b/wfserver_resource.rc @@ -0,0 +1,37 @@ +#include + +IDI_ICON1 ICON DISCARDABLE "C:\\Users\\Phil\\source\\repos\\wfview\\resources\\wfview.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,0 + PRODUCTVERSION 0,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "\0" + VALUE "FileVersion", "0.0.0.0\0" + VALUE "LegalCopyright", "\0" + VALUE "OriginalFilename", "wfserver.exe\0" + VALUE "ProductName", "wfserver\0" + VALUE "ProductVersion", "0.0.0.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1200 + END + END +/* End of Version info */ + diff --git a/wfview.sln b/wfview.sln index ff4a8cd..d1ee00c 100644 --- a/wfview.sln +++ b/wfview.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30804.86 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wfview", "wfview.vcxproj", "{326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wfserver", "wfserver.vcxproj", "{00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -15,6 +17,10 @@ Global {326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}.Debug|x86.Build.0 = Debug|Win32 {326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}.Release|x86.ActiveCfg = Release|Win32 {326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}.Release|x86.Build.0 = Release|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Debug|x86.ActiveCfg = Debug|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Debug|x86.Build.0 = Debug|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Release|x86.ActiveCfg = Release|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/wfview.vcxproj b/wfview.vcxproj index 9357e18..bd3677c 100644 --- a/wfview.vcxproj +++ b/wfview.vcxproj @@ -57,7 +57,7 @@ Sync release\ MaxSpeed - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="01ea44d";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="28812be";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false MultiThreadedDLL @@ -85,7 +85,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"01ea44d\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"28812be\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h @@ -99,7 +99,7 @@ Sync debug\ Disabled - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="01ea44d";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="28812be";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true @@ -124,7 +124,7 @@ 0 - _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"01ea44d\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _WINDOWS;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"28812be\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cppUic'ing %(Identity)...$(ProjectDir)ui_%(Filename).h