JS8Call-Improved master
Loading...
Searching...
No Matches
mainwindow.h
1// -*- Mode: C++ -*-
2#ifndef MAINWINDOW_H
3#define MAINWINDOW_H
4
5#include "JS8_Audio/AudioDevice.h"
6#include "JS8_Audio/NotificationAudio.h"
7#include "JS8_Audio/SoundInput.h"
8#include "JS8_Audio/SoundOutput.h"
9#include "JS8_Include/EventFilter.h"
10#include "JS8_Include/commons.h"
11#include "JS8_Include/qpriorityqueue.h"
12#include "JS8_JSC/JSC_checker.h"
13#include "JS8_Logbook/LogBook.h"
16#include "JS8_Main/Bands.h"
17#include "JS8_Main/DirectedMessageHighlighter.h"
18#include "JS8_Main/DriftingDateTime.h"
19#include "JS8_Main/FrequencyList.h"
20#include "JS8_Main/Geodesic.h"
21#include "JS8_Main/HelpTextWindow.h"
22#include "JS8_Main/Inbox.h"
23#include "JS8_Main/JS8MessageBox.h"
24#include "JS8_Main/MessageClient.h"
25#include "JS8_Main/MessageServer.h"
26#include "JS8_Main/Modes.h"
27#include "JS8_Main/MultiSettings.h"
29#include "JS8_Main/ProcessThread.h"
30#include "JS8_Main/Radio.h"
31#include "JS8_Main/SelfDestructMessageBox.h"
32#include "JS8_Main/SignalMeter.h"
33#include "JS8_Main/StationList.h"
34#include "JS8_Main/TxLoop.h"
35#include "JS8_Main/Varicode.h"
36#include "JS8_Main/qt_helpers.h"
37#include "JS8_Main/revision_utils.h"
38#include "JS8_Mode/DecodedText.h"
39#include "JS8_Mode/Decoder.h"
40#include "JS8_Mode/Detector.h"
41#include "JS8_Mode/JS8.h"
42#include "JS8_Mode/JS8Submode.h"
43#include "JS8_Mode/Modulator.h"
44#include "JS8_Network/NetworkAccessManager.h"
45#include "JS8_Network/PSKReporter.h"
46#include "JS8_Network/SpotClient.h"
47#include "JS8_Network/TCPClient.h"
48#include "JS8_Transceiver/Transceiver.h"
49#include "JS8_Transceiver/TransceiverFactory.h"
50#include "JS8_UDP/WSJTXMessageClient.h"
51#include "JS8_UDP/WSJTXMessageMapper.h"
52#include "JS8_UI/About.h"
53#include "JS8_UI/Configuration.h"
54#include "JS8_UI/WideGraph.h"
55#include "JS8_UI/MessagePanel.h"
56#include "LogQSO.h"
57#include "MessageReplyDialog.h"
58#include "ui_mainwindow.h"
59
60#include <QAbstractSocket>
61#include <QAction>
62#include <QActionGroup>
63#include <QApplication>
64#include <QAudioDevice>
65#include <QByteArrayView>
66#include <QCursor>
67#include <QDateTime>
68#include <QDesktopServices>
69#include <QDir>
70#include <QDockWidget>
71#include <QElapsedTimer>
72#include <QFileDialog>
73#include <QHash>
74#include <QHostAddress>
75#include <QHostInfo>
76#include <QInputDialog>
77#include <QLabel>
78#include <QLineEdit>
79#include <QList>
80#include <QLoggingCategory>
81#include <QMainWindow>
82#include <QMdiSubWindow>
83#include <QMutex>
84#include <QMutexLocker>
85#include <QNetworkAccessManager>
86#include <QNetworkReply>
87#include <QNetworkRequest>
88#include <QPair>
89#include <QPixmap>
90#include <QPointer>
91#include <QProgressBar>
92#include <QProgressDialog>
93#include <QRegularExpression>
94#include <QRegularExpressionValidator>
95#include <QScopedPointer>
96#include <QScrollBar>
97#include <QSet>
98#include <QSoundEffect>
99#include <QStandardPaths>
100#include <QStringBuilder>
101#include <QTableWidget>
102#include <QTextEdit>
103#include <QThread>
104#include <QTime>
105#include <QTimeZone>
106#include <QTimer>
107#include <QToolTip>
108#include <QUdpSocket>
109#include <QUrl>
110#include <QVariant>
111#include <QVector>
112#include <QVersionNumber>
113#include <QtConcurrent/QtConcurrentRun>
114#include <QtGui>
115#include <boost/crc.hpp>
116#include <fftw3.h>
117
118#include <algorithm>
119#include <array>
120#include <cmath>
121#include <complex>
122#include <cstring>
123#include <functional>
124#include <iterator>
125#include <mutex>
126#include <stdexcept>
127#include <string_view>
128#include <unordered_map>
129#include <vector>
130
131Q_DECLARE_LOGGING_CATEGORY(mainwindow_js8)
132
133extern int volatile itone[JS8_NUM_SYMBOLS]; // Audio tones for all Tx symbols
134
135//--------------------------------------------------------------- mainwindow
136// How often to poll the UI, in MS.
137// Some things may depend on this being a divisor of 1000.
138constexpr quint32 UI_POLL_INTERVAL_MS = 100;
139
140namespace {
141namespace Default {
142constexpr Radio::Frequency DIAL_FREQUENCY = 14078000;
143constexpr auto FREQUENCY = 1500;
144constexpr auto SUBMODE = Varicode::JS8CallNormal;
145} // namespace Default
146
147namespace State {
148constexpr auto RX = 1;
149constexpr auto TX = 2;
150} // namespace State
151} // namespace
152
153namespace Ui {
154class UI_Constructor;
155}
156
157class QSettings;
158class QLineEdit;
159class QFont;
160class QHostInfo;
161class WideGraph;
162class LogQSO;
163class Transceiver;
164class MessageClient;
165class QTime;
166class HelpTextWindow;
167class SoundOutput;
168class Modulator;
169class SoundInput;
170class Detector;
171class AprsInboundRelay;
172class MultiSettings;
173class DecodedText;
174class JSCChecker;
175class MessagePanel;
176
177using namespace std;
178typedef std::function<void()> Callback;
179
180class WSJTXMessageMapper; // Forward declaration
181
182class UI_Constructor : public QMainWindow {
183 Q_OBJECT;
184 friend class WSJTXMessageMapper; // Allow WSJTXMessageMapper to access
185 // private members
186
187 struct CallDetail;
188 struct CommandDetail;
189
190 public:
191 using Frequency = Radio::Frequency;
192 using FrequencyDelta = Radio::FrequencyDelta;
193 using Mode = Modes::Mode;
194
195 explicit UI_Constructor(QString const &program_info,
196 QDir const &temp_directory, bool multiple,
197 MultiSettings *settings, QWidget *parent = nullptr);
199
200 private:
201 struct SortByReverse {
202 QString by;
203 bool reverse;
204 };
205
216 bool m_stopTxButtonIsLongterm;
217 bool m_hbButtonIsLongterm;
218 bool m_cqButtonIsLongterm;
219
220 public slots:
221 void showSoundInError(const QString &errorMsg);
222 void showSoundOutError(const QString &errorMsg);
223 void showStatusMessage(const QString &statusMsg);
224 void dataSink(qint64 frames);
230 void guiUpdate();
231 void setXIT(int n);
232 void qsy(int hzDelta);
233 void onDriftChanged(qint64 new_drift_ms);
234 void setFreqOffsetForRestore(int freq, bool shouldRestore);
235 bool tryRestoreFreqOffset();
236 void changeFreq(int);
237
238 bool hasExistingMessageBufferToMe(int *pOffset);
239 bool hasExistingMessageBuffer(int submode, int offset, bool drift,
240 int *pPrevOffset);
241 bool hasClosedExistingMessageBuffer(int offset);
242 void logCallActivity(CallDetail d, bool spot = true);
243 void logHeardGraph(QString from, QString to);
244 QString lookupCallInCompoundCache(QString const &call);
245 void cacheActivity(QString key);
246 void restoreActivity(QString key);
247 void clearActivity();
248 void clearBandActivity();
249 void clearRXActivity();
250 void clearCallActivity();
251 void createGroupCallsignTableRows(QTableWidget *table,
252 const QString &selectedCall,
253 bool &showIconColumn);
254 void displayTextForFreq(QString text, int freq, QDateTime date, bool isTx,
255 bool isNewLine, bool isLast);
256 void writeNoticeTextToUI(QDateTime date, QString text);
257 int writeMessageTextToUI(QDateTime date, QString text, int freq, bool isTx,
258 int block = -1);
259 bool isMessageQueuedForTransmit();
260 bool isInDecodeDelayThreshold(int seconds);
261 void prependMessageText(QString text);
262 void addMessageText(QString text, bool clear = false,
263 bool selectFirstPlaceholder = false);
264 void confirmThenEnqueueMessage(int timeout, int priority, QString message,
265 int offset, Callback c);
266 void enqueueMessage(int priority, QString message, int offset, Callback c);
267 void resetMessage();
268 void resetMessageUI();
269 void restoreMessage();
270 void initializeDummyData();
271 void initializeGroupMessage();
272 bool ensureCallsignSet(bool alert = true);
273 bool ensureKeyNotStuck(QString const &text);
274 bool ensureNotIdle();
275 bool ensureCanTransmit();
276 bool ensureCreateMessageReady(const QString &text);
277 QString createMessage(QString const &text, bool *pDisableTypeahead);
278 QString appendMessage(QString const &text, bool isData,
279 bool *pDisableTypeahead);
280 QString createMessageTransmitQueue(QString const &text, bool reset,
281 bool isData, bool *pDisableTypeahead);
283 QPair<QString, int> popMessageFrame();
284 void tryNotify(const QString &key);
285 void processDecodeEvent(JS8::Event::Variant const &);
286
287 void updateCQButtonDisplay();
288 void updateHBButtonDisplay();
289
290 protected:
291 void keyPressEvent(QKeyEvent *) override;
292 void closeEvent(QCloseEvent *) override;
293 void childEvent(QChildEvent *) override;
294 bool eventFilter(QObject *, QEvent *) override;
295
296 private slots:
297 void initialize_fonts();
298 void on_menuModeJS8_aboutToShow();
299 void on_menuControl_aboutToShow();
300 void on_actionCheck_for_Updates_triggered();
301 void on_actionEnable_Monitor_RX_toggled(bool checked);
302 void on_actionEnable_Transmitter_TX_toggled(bool checked);
303 void on_actionEnable_Reporting_SPOT_toggled(bool checked);
304 void on_actionEnable_Tuning_Tone_TUNE_toggled(bool checked);
305 void on_menuWindow_aboutToShow();
306 void on_actionFocus_Message_Receive_Area_triggered();
307 void on_actionFocus_Message_Reply_Area_triggered();
308 void on_actionFocus_Band_Activity_Table_triggered();
309 void on_actionFocus_Call_Activity_Table_triggered();
310 void on_actionClear_All_Activity_triggered();
311 void on_actionClear_Band_Activity_triggered();
312 void on_actionClear_RX_Activity_triggered();
313 void on_actionClear_Call_Activity_triggered();
314 void on_actionSetOffset_triggered();
315 void on_actionShow_Fullscreen_triggered(bool checked);
316 void on_actionShow_Statusbar_triggered(bool checked);
317 void on_actionShow_Frequency_Clock_triggered(bool checked);
318 void on_actionShow_Band_Activity_triggered(bool checked);
319 void on_actionShow_Band_Heartbeats_and_ACKs_triggered(bool checked);
320 void on_actionShow_Call_Activity_triggered(bool checked);
321 void on_actionShow_Waterfall_triggered(bool checked);
322 void on_actionShow_Waterfall_Controls_triggered(bool checked);
323 void on_actionShow_Waterfall_Time_Drift_Controls_triggered(bool checked);
324 void on_actionReset_Window_Sizes_triggered();
325 void on_actionSettings_triggered();
326 void openSettings(int tab = 0);
327 void prepareApi();
328 void prepareSpotting();
329 void on_spotButton_clicked(bool checked);
330 void on_monitorButton_clicked(bool);
331 void on_actionAbout_triggered();
332 void resetPushButtonToggleText(QPushButton *btn);
333 void on_stopTxButton_clicked();
334 void on_dialFreqUpButton_clicked();
335 void on_dialFreqDownButton_clicked();
336 void on_actionAdd_Log_Entry_triggered();
337 void on_actionOpen_log_directory_triggered();
338 void on_actionCopyright_Notice_triggered();
339 void on_actionUser_Guide_triggered();
340 bool decode(qint32 k);
341 bool isDecodeReady(int submode, qint32 k, qint32 k0,
342 qint32 *pCurrentDecodeStart, qint32 *pNextDecodeStart,
343 qint32 *pStart, qint32 *pSz, qint32 *pCycle);
344 bool decodeEnqueueReady(qint32 k, qint32 k0);
345 bool decodeEnqueueReadyExperiment(qint32 k, qint32 k0);
346 bool decodeProcessQueue(qint32 *pSubmode);
347 void decodeStart();
348 void decodeBusy(bool b);
349 void decodeDone();
350 void on_startTxButton_toggled(bool checked);
351 void toggleTx(bool start);
352 void on_logQSOButton_clicked();
353 void on_actionModeJS8HB_toggled(bool checked);
354 void on_actionModeJS8Normal_triggered();
355 void on_actionModeJS8Fast_triggered();
356 void on_actionModeJS8Turbo_triggered();
357 void on_actionModeJS8Slow_triggered();
358 void on_actionModeJS8Ultra_triggered();
359 void on_actionHeartbeatAcknowledgements_toggled(bool checked);
360 void on_actionModeMultiDecoder_toggled(bool checked);
361 void on_actionModeAutoreply_toggled(bool checked);
362 bool canCurrentModeSendHeartbeat() const;
363 void prepareMonitorControls();
364 void prepareHeartbeatMode(bool enabled);
365 void f11f12(int n);
366 void on_actionErase_ALL_TXT_triggered();
367 void on_actionErase_js8call_log_adi_triggered();
368 void startTx();
369 void stopTx();
370 void stopTx2();
371 void buildFrequencyMenu(QMenu *menu);
372 void buildHeartbeatMenu(QMenu *menu);
373 void buildCQMenu(QMenu *menu);
374 void buildRepeatMenu(QMenu *menu, QPushButton *button, bool isLowInterval,
375 int *interval);
376 void sendHB();
377 void sendHeartbeatAck(QString to, int snr, QString extra);
378 void on_hbMacroButton_toggled(bool checked);
379 void on_hbMacroButton_clicked();
380 void sendCQ(bool repeat = false);
381 void on_cqMacroButton_toggled(bool checked);
382 void on_cqMacroButton_clicked();
383 void on_replyMacroButton_clicked();
384 void on_snrMacroButton_clicked();
385 void on_infoMacroButton_clicked();
386 void on_statusMacroButton_clicked();
387 void setShowColumn(QString tableKey, QString columnKey, bool value);
388 bool showColumn(QString tableKey, QString columnKey, bool default_ = true);
389 void buildShowColumnsMenu(QMenu *menu, QString tableKey);
390 void setSortBy(QString key, QString value);
391 QString getSortBy(QString const &key, QString const &defaultValue) const;
392 SortByReverse getSortByReverse(QString const &key,
393 QString const &defaultValue) const;
394 void buildSortByMenu(QMenu *menu, QString key, QString defaultValue,
395 QList<QPair<QString, QString>> values);
396 void buildBandActivitySortByMenu(QMenu *menu);
397 void buildCallActivitySortByMenu(QMenu *menu);
398 void buildQueryMenu(QMenu *, QString callsign);
399 QMap<QString, QString> buildMacroValues();
400 void buildColumnLabelMap();
401 void buildSuggestionsMenu(QMenu *menu, QTextEdit *edit,
402 const QPoint &point);
403 void buildSavedMessagesMenu(QMenu *menu);
404 void buildRelayMenu(QMenu *menu);
405 QAction *buildRelayAction(QString call);
406 void buildEditMenu(QMenu *, QTextEdit *);
407 void on_queryButton_pressed();
408 void on_macrosMacroButton_pressed();
409 void on_deselectButton_pressed();
410 void on_tableWidgetRXAll_cellClicked(int row, int col);
411 void on_tableWidgetRXAll_cellDoubleClicked(int row, int col);
412 QString generateCallDetail(QString selectedCall);
413 void on_tableWidgetCalls_cellClicked(int row, int col);
414 void on_tableWidgetCalls_cellDoubleClicked(int row, int col);
415 QList<QPair<QString, int>> buildMessageFrames(QString const &text,
416 bool isData,
417 bool *pDisableTypeahead);
418 bool prepareNextMessageFrame();
419 bool isFreqOffsetFree(int f, int bw);
420 int findFreeFreqOffset(int fmin, int fmax, int bw);
421 void setDrift(int n);
422 void on_tuneButton_clicked(bool);
423 void acceptQSO(QDateTime const &, QString const &call, QString const &grid,
424 Frequency dial_freq, QString const &mode,
425 QString const &submode, QString const &rpt_sent,
426 QString const &rpt_received, QString const &comments,
427 QString const &name, QDateTime const &QSO_date_on,
428 QString const &operator_call, QString const &my_call,
429 QString const &my_grid, QByteArray const &ADIF,
430 QVariantMap const &additionalFields);
431 void on_readFreq_clicked();
432 void on_outAttenuation_valueChanged(int);
433 void rigOpen();
434 void handle_transceiver_update(Transceiver::TransceiverState const &);
435 void handle_transceiver_failure(QString const &reason);
436 void band_changed();
437 void monitor(bool);
438 void end_tuning();
439 void stop_tuning();
440 void stopTuneATU();
441 void auto_tx_mode(bool);
442 void on_monitorButton_toggled(bool checked);
443 void on_monitorTxButton_toggled(bool checked);
444 void on_tuneButton_toggled(bool checked);
445 void on_spotButton_toggled(bool checked);
446
447 void emitPTT(bool on);
448 void emitTones();
449 void udpNetworkMessage(Message const &message);
450 void tcpNetworkMessage(Message const &message);
451 void networkMessage(Message const &message);
452 bool canSendNetworkMessage();
453 void sendNetworkMessage(QString const &type, QString const &message);
454 void sendNetworkMessage(QString const &type, QString const &message,
455 const QVariantMap &params);
456 void pskReporterError(QString const &);
457 void TxAgain();
458 void checkVersion(bool alertOnUpToDate);
459 void checkStartupWarnings();
460 void clearCallsignSelected();
461 void refreshTextDisplay();
462
463 void manualBandHop(const StationList::Station station);
464
465 private:
466 Q_SIGNAL void apiSetMaxConnections(int n);
467 Q_SIGNAL void apiSetServer(QString host, quint16 port);
468 Q_SIGNAL void apiStartServer();
469 Q_SIGNAL void apiStopServer();
470
471 Q_SIGNAL void aprsClientEnqueueSpot(QString by_call, QString from_call,
472 QString grid, QString comment);
473 Q_SIGNAL void aprsClientEnqueueThirdParty(QString by_call,
474 QString from_call, QString text);
481 Q_SIGNAL void aprsClientEnqueueAck(QString from_call, QString to_call,
482 QString messageId);
483 Q_SIGNAL void aprsClientSetSkipPercent(float skipPercent);
484 Q_SIGNAL void aprsClientSetIncomingRelayEnabled(bool enabled);
485 Q_SIGNAL void aprsClientSetServer(QString host, quint16 port);
486 Q_SIGNAL void aprsClientSetPaused(bool paused);
487 Q_SIGNAL void aprsClientSetLocalStation(QString mycall, QString passcode);
488 Q_SIGNAL void aprsClientSendReports();
489
490 Q_SIGNAL void pskReporterSendReport(bool);
491 Q_SIGNAL void pskReporterSetLocalStation(QString, QString, QString);
492 Q_SIGNAL void pskReporterAddRemoteStation(QString, QString,
493 Radio::Frequency, QString, int,
494 QDateTime);
495
496 Q_SIGNAL void spotClientSetLocalStation(QString, QString, QString);
497 Q_SIGNAL void spotClientEnqueueCmd(QString, QString, QString, QString,
498 QString, QString, QString, int, int, int,
499 int);
500 Q_SIGNAL void spotClientEnqueueSpot(QString, QString, int, int, int, int);
501
502 Q_SIGNAL void decodedLineReady(QByteArray t);
503 Q_SIGNAL void playNotification(const QString &name);
504 Q_SIGNAL void initializeNotificationAudioOutputStream(const QAudioDevice &,
505 unsigned) const;
506 Q_SIGNAL void initializeAudioOutputStream(QAudioDevice, unsigned channels,
507 unsigned msBuffered) const;
508 Q_SIGNAL void stopAudioOutputStream() const;
509 Q_SIGNAL void startAudioInputStream(QAudioDevice const &,
510 int framesPerBuffer, AudioDevice *sink,
511 AudioDevice::Channel) const;
512 Q_SIGNAL void suspendAudioInputStream() const;
513 Q_SIGNAL void resumeAudioInputStream() const;
514 Q_SIGNAL void startDetector(AudioDevice::Channel) const;
515 Q_SIGNAL void FFTSize(unsigned) const;
516 Q_SIGNAL void detectorClose() const;
517 Q_SIGNAL void finished() const;
518 Q_SIGNAL void transmitFrequency(double) const;
519 Q_SIGNAL void endTransmitMessage(bool quick = false) const;
520 Q_SIGNAL void tune(bool = true) const;
521 Q_SIGNAL void sendMessage(double frequency, int submode, double txDelay,
522 SoundOutput *, AudioDevice::Channel) const;
523 Q_SIGNAL void outAttenuationChanged(qreal) const;
524 Q_SIGNAL void toggleShorthand() const;
525 Q_SIGNAL void submodeChanged(Varicode::SubmodeType) const;
526
527 Q_SIGNAL void messageAdded(int) const;
528
529 private:
530 QByteArray wisdomFileName() const;
531
532 void writeAllTxt(QStringView message);
533 void writeMsgTxt(QStringView message, int snr, int offset);
534
535 void currentTextChanged();
536 void tableSelectionChanged(QItemSelection const &, QItemSelection const &);
537 void setupJS8();
538 void applyPillSettings();
539
540 int freq() const { return m_freq; }
541
543 void refuseToSendIn30mWSPRBand();
544
545 void prepareSending(qint64 nowMS);
546
548 void updateClockUI(const QDateTime &);
549
550 void setFreq(int);
551 void transmit();
552
553 bool presentlyWantHBReplies();
554
555 QString m_nextFreeTextMsg;
556
557 NetworkAccessManager m_network_manager;
558 bool m_valid;
559 [[maybe_unused]] bool m_multiple; // Used only in Windows builds
560 MultiSettings *m_multi_settings;
561 QPushButton *m_configurations_button;
562 QSettings *m_settings;
563 bool m_settings_read;
564 QScopedPointer<Ui::UI_Constructor> ui;
565
566 // other windows
567 Configuration m_config;
568 JS8MessageBox m_rigErrorMessageBox;
569
570 QDockWidget* messageDock_ = nullptr;
571 MessagePanel* messagePanel_ = nullptr;
572 QDialog* messageFloatDialog_ = nullptr;
573
574 enum class MessageHost { Dock, Dialog };
575 MessageHost messageHost_ = MessageHost::Dock;
576
577 QScopedPointer<WideGraph> m_wideGraph;
578 QScopedPointer<LogQSO> m_logDlg;
579 QScopedPointer<HelpTextWindow> m_shortcuts;
580 QScopedPointer<HelpTextWindow> m_prefixes;
581 QScopedPointer<HelpTextWindow> m_mouseCmnds;
582
584 Frequency m_lastDialFreq;
585 QString m_lastBand;
586
587 Detector *m_detector;
588 unsigned m_FFTSize;
589 SoundInput *m_soundInput;
590 Modulator *m_modulator;
591 SoundOutput *m_soundOutput;
592 NotificationAudio *m_notification;
593
594 // Configuration might one day offer to send a txDelayChanged signal.
595 // As long as it doesn't, we poll and compare with the previous value.
596 double m_TxDelay; // in seconds.
597
598 TxLoop *m_cq_loop;
599 TxLoop *m_hb_loop;
600
601 QThread m_networkThread;
602 QThread m_audioThread;
603 QThread m_notificationAudioThread;
604 JS8::Decoder m_decoder;
605
606 qint64 m_secBandChanged;
607
608 Frequency m_freqNominal;
609 Frequency m_freqTxNominal;
610
611 int m_freq;
612
613 qint32 m_XIT;
614 qint32 m_sec0;
615 qint32 m_RxLog;
616 qint32 m_nutc0;
617 // The period of the current submode, in seconds. (15 for normal, 10 for
618 // fast, ...)
619 qint32 m_TRperiod;
620 qint32 m_inGain;
621 qint32 m_idleMinutes;
622 qint32 m_nSubMode;
623 FrequencyList_v3::const_iterator m_frequency_list_fcal_iter;
624 qint32 m_i3bit;
625
626 bool m_btxok; // True if OK to transmit
627 bool m_decoderBusy;
628 QString m_decoderBusyBand;
629 QMap<qint32, qint32>
630 m_lastDecodeStartMap; // submode, decode k start position
631 QMap<qint32, qint32>
632 m_lastDecodeCycleMap; // JS8 40 & JS8 60 submodes, last enqueued cycle start
633 Radio::Frequency m_decoderBusyFreq;
634 QDateTime m_decoderBusyStartTime;
635 bool m_auto;
636 bool m_restart;
637 bool m_bDecoded;
638 int m_currentMessageType;
639 QString m_currentMessage;
640 int m_currentMessageBits;
641 int m_lastMessageType;
642 QString m_lastMessageSent;
643 bool m_tuneup;
644 bool m_isTimeToSend;
645
646 int m_ihsym;
647 float m_px;
648 float m_pxmax;
649 float m_df3;
650 quint32 m_iptt = 0;
651 quint32 m_iptt0;
652 bool m_btxok0;
653 double m_onAirFreq0;
654 bool m_first_error;
655
656 char m_msg[100][80];
657
658 // labels in status bar
659 QLabel tx_status_label;
660 QLabel config_label;
661 QLabel mode_label;
662 QLabel last_tx_label;
663 QLabel auto_tx_label;
664 QProgressBar progressBar;
665 QLabel wpm_label;
666
667 // QPointer<QProcess> proc_js8;
668
669 QTimer m_guiTimer;
670 // Timer to switch off PTT after end of transmission.
671 QTimer pttReleaseTimer;
672 QTimer logQSOTimer;
673 QTimer tuneButtonTimer;
674 QTimer tuneATU_Timer;
675 QTimer TxAgainTimer;
676 QTimer minuteTimer;
677 QString m_baseCall;
678 QString m_hisCall;
679 QString m_hisGrid;
680 QString m_appDir;
681 QString m_palette;
682 QString m_rptSent;
683 QString m_rptRcvd;
684 QString m_msgSent0;
685 QString m_opCall;
686
687 struct CallDetail {
688 QString call;
689 QString through;
690 QString grid;
691 int dial;
692 int offset;
693 QDateTime cqTimestamp;
694 QDateTime ackTimestamp;
695 QDateTime utcTimestamp;
696 int snr;
697 int bits;
698 float tdrift;
699 int submode;
700 };
701
702 struct CommandDetail {
703 bool isCompound;
704 bool isBuffered;
705 QString from;
706 QString to;
707 QString cmd;
708 int dial;
709 int offset;
710 QDateTime utcTimestamp;
711 int snr;
712 int bits;
713 QString grid;
714 QString text;
715 QString extra;
716 float tdrift;
717 int submode;
718 QString relayPath;
719 };
720
721 struct ActivityDetail {
722 bool isLowConfidence;
723 bool isCompound;
724 bool isDirected;
725 bool isBuffered;
726 int bits;
727 int dial;
728 int offset;
729 QString text;
730 QDateTime utcTimestamp;
731 int snr;
732 bool shouldDisplay;
733 float tdrift;
734 int submode;
735 };
736
737 struct MessageBuffer {
738 CommandDetail cmd;
739 QQueue<CallDetail> compound;
741 };
742
743 QString m_prevSelectedCallsign;
744 int m_bandActivityWidth;
745 int m_callActivityWidth;
746 int m_textActivityWidth;
747 int m_waterfallHeight;
748 bool m_bandActivityWasVisible;
749 bool m_rxDirty;
750 bool m_rxDisplayDirty;
751 int m_txFrameCountEstimate;
752 int m_txFrameCount;
753 int m_txFrameCountSent;
754 QTimer m_txTextDirtyDebounce;
755 bool m_txTextDirty;
756 QString m_txTextDirtyLastText;
757 QString m_txTextDirtyLastSelectedCall;
758 QString m_lastTxMessage;
759 QString m_totalTxMessage;
760
761 // moved from mainwindow.cpp, is used in multiple functions
762 QString since(QDateTime const &time) {
763 auto const delta = time.secsTo(DriftingDateTime::currentDateTimeUtc());
764
765 if (delta >= 60 * 60 * 24)
766 return QString("%1d").arg(delta / (60 * 60 * 24));
767 else if (delta >= 60 * 60)
768 return QString("%1h").arg(delta / (60 * 60));
769 else if (delta >= 60)
770 return QString("%1m").arg(delta / (60));
771 else if (delta >= 15)
772 return QString("%1s").arg(delta - (delta % 15));
773 else
774 return QString("now");
775 }
776
777 QDateTime m_lastTxStartTime;
778 QDateTime m_lastTxStopTime;
779 qint32 m_driftMsMMA;
780 qint32 m_driftMsMMA_N;
781
782 // moved from mainwindow.cpp, is used in multiple functions
783 auto replaceMacros(QString const &text,
784 QMap<QString, QString> const &values, bool const prune) {
785 QString output = text;
786
787 for (auto const [key, value] : values.asKeyValueRange()) {
788 output = output.replace(key, value.toUpper());
789 }
790
791 return prune ? output.replace(QRegularExpression("[<](?:[^>]+)[>]"), "")
792 : output;
793 }
794
795 QList<int> generateOffsets(int minOffset, int maxOffset) {
796 QList<int> offsets;
797
798 // TODO: these offsets aren't ordered correctly...
799
800 for (int i = minOffset; i <= maxOffset; i++) {
801 offsets.append(i);
802 }
803 return offsets;
804 }
805
806 enum Priority {
807 PriorityLow = 10,
808 PriorityNormal = 100,
809 PriorityHigh = 1000
810 };
811
812 struct PrioritizedMessage {
813 QDateTime date;
814 int priority;
815 QString message;
816 int offset;
817 Callback callback;
818
819 friend bool operator<(PrioritizedMessage const &a,
820 PrioritizedMessage const &b) {
821 if (a.priority < b.priority) {
822 return true;
823 }
824 return a.date < b.date;
825 }
826 };
827
828 struct CachedDirectedType {
829 bool isAllcall;
830 QDateTime date;
831 };
832
833 struct DecodeParams {
834 int submode;
835 int start;
836 int sz;
837 };
838
839 struct FrameCacheKey {
840 int submode;
841 QString frame;
842
843 FrameCacheKey(int submode, QString frame)
844 : submode(submode), frame(std::move(frame)) {}
845
846 bool operator==(FrameCacheKey const &) const noexcept = default;
847
848 struct Hash {
849 std::size_t operator()(FrameCacheKey const &key) const noexcept {
850 std::size_t const h1 = std::hash<int>{}(key.submode);
851 std::size_t const h2 = qHash(key.frame);
852 return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
853 }
854 };
855 };
856
857 using FrameCache =
858 std::unordered_map<FrameCacheKey, QDateTime, FrameCacheKey::Hash>;
859 using BandActivity = QMap<int, QList<ActivityDetail>>;
860
861 QQueue<DecodeParams> m_decoderQueue;
862 FrameCache m_messageDupeCache; // submode, frame -> date seen
863 QVariantMap m_showColumnsCache; // table column:key -> show boolean
864 QVariantMap m_sortCache; // table key -> sort by
865 QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent
866 QQueue<QPair<QString, int>> m_txFrameQueue; // frames to be sent
867 QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue
868 QQueue<CommandDetail>
869 m_rxCommandQueue; // command queue for processing commands
870 QQueue<CallDetail>
871 m_rxCallQueue; // call detail queue for spots to pskreporter
872 QMap<QString, QString>
873 m_compoundCallCache; // base callsign -> compound callsign
874 QCache<QString, QDateTime> m_txAllcallCommandCache; // callsign -> last tx
875 QCache<int, QDateTime> m_rxRecentCache; // freq -> last rx
876 QCache<int, CachedDirectedType>
877 m_rxDirectedCache; // freq -> last directed rx
878 QCache<QString, int> m_rxCallCache; // call -> last freq seen
879 QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
880 BandActivity m_bandActivity; // freq -> [(text, last timestamp), ...]
881 QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
882 int m_lastClosedMessageBufferOffset;
883 QMap<QString, CallDetail>
884 m_callActivity; // call -> (last freq, last timestamp)
885
886 QMap<int, QString> m_origRxHeaderLabelMap; // colIndex, label
887 QMap<int, QString> m_origCallActivityHeaderLabelMap; // colIndex, label
888 QMap<QString, QString> m_columnLabelMap; // full, minimal
889
890 QMap<QString, QSet<QString>>
891 m_heardGraphOutgoing; // callsign -> [stations who've this callsign has
892 // heard]
893 QMap<QString, QSet<QString>>
894 m_heardGraphIncoming; // callsign -> [stations who've heard this
895 // callsign]
896
897 QMap<QString, int> m_rxInboxCountCache; // call -> count
898
899 QMap<QString, QMap<QString, CallDetail>>
900 m_callActivityBandCache; // band -> call activity
901 QMap<QString, QMap<int, QList<ActivityDetail>>>
902 m_bandActivityBandCache; // band -> band activity
903 QMap<QString, QString> m_rxTextBandCache; // band -> rx text
904 QMap<QString, QMap<QString, QSet<QString>>>
905 m_heardGraphOutgoingBandCache; // band -> heard in
906 QMap<QString, QMap<QString, QSet<QString>>>
907 m_heardGraphIncomingBandCache; // band -> heard out
908
909 // Pending autoreply confirmations (TCP-based, remplace Qt dialog en headless)
910 struct PendingConfirmation {
911 int id;
912 int priority;
913 QString message;
914 int offset;
915 Callback callback;
916 QTimer *timer;
917 };
918 int m_nextConfirmId = 0;
919 QMap<int, PendingConfirmation> m_pendingConfirmations;
920
921 QMap<QString, QDateTime>
922 m_callSelectedTime; // call -> timestamp when callsign was last selected
927 QHash<QString, QDateTime> m_aprsRelayDedupCache;
928 QSet<QString> m_callSeenHeartbeat; // call
929 int m_previousFreq;
930 bool m_shouldRestoreFreq;
931 bool m_bandHopped;
932 Frequency m_bandHoppedFreq;
933
935 int m_hbInterval;
937 int m_cqInterval;
938
940 bool m_hbPaused;
941
942 QDateTime m_dateTimeQSOOn;
943 QDateTime m_dateTimeLastTX;
944
945 LogBook m_logBook;
946 unsigned m_msAudioOutputBuffered;
947 unsigned m_framesAudioInputBuffered;
948 QThread::Priority m_audioThreadPriority;
949 QThread::Priority m_notificationAudioThreadPriority;
950 QThread::Priority m_decoderThreadPriority;
951 QThread::Priority m_networkThreadPriority;
952 bool m_splitMode;
953 bool m_monitoring;
954 bool m_generateAudioWhenPttConfirmedByTX;
955 bool m_transmitting;
956 bool m_tune;
957 bool m_tx_watchdog; // true when watchdog triggered
958 bool m_block_pwr_tooltip;
959 bool m_PwrBandSetOK;
960 Frequency m_lastMonitoredFrequency;
961 MessageClient *m_messageClient;
962 MessageServer *m_messageServer;
963 WSJTXMessageClient *m_wsjtxMessageClient;
964 WSJTXMessageMapper *m_wsjtxMessageMapper;
965 TCPClient *m_n3fjpClient;
966 PSKReporter *m_pskReporter;
967 SpotClient *m_spotClient;
968 APRSISClient *m_aprsClient;
969 AprsInboundRelay *m_aprsInboundRelay;
970 QVariantHash m_pwrBandTxMemory; // Remembers power level by band
971 QVariantHash
972 m_pwrBandTuneMemory; // Remembers power level by band for tuning
973 QByteArray m_geometryNoControls;
974
975 //---------------------------------------------------- private functions
976 void readSettings();
977 void set_application_font(QFont const &);
978 void writeSettings();
979 void createStatusBar();
980 void statusChanged();
981 void rigFailure(QString const &reason);
982 void spotSetLocal();
983 void pskSetLocal();
984 void aprsSetLocal();
985 void spotReport(int submode, int dial, int offset, int snr,
986 QString const &callsign, QString const &grid);
987 void spotCmd(CommandDetail const &cmd);
988 void spotAprsCmd(CommandDetail const &cmd);
989 void pskLogReport(QString const &mode, int dial, int offset, int snr,
990 QString const &callsign, QString const &grid,
991 QDateTime const &utcTimestamp);
992 void spotAprsGrid(int dial, int offset, int snr, QString callsign,
993 QString grid);
994 Radio::Frequency dialFrequency();
995 void setSubmode(int submode);
996 void updateCurrentBand();
997 void displayDialFrequency();
998 void transmitDisplay(bool);
999 void postDecode(bool is_new, QString const &message);
1000 void displayTransmit();
1001 void updateModeButtonText();
1002 void updateButtonDisplay();
1003 void updateTextDisplay();
1004 void updateTextWordCheckerDisplay();
1005 void updateTextStatsDisplay(QString text, int count);
1006 void updateTxButtonDisplay();
1007 bool isMyCallIncluded(QString const &text);
1008 bool isAllCallIncluded(QString const &text);
1009 bool isGroupCallIncluded(const QString &text);
1010 QString callsignSelected(bool useInputText = false);
1011 void callsignSelectedChanged(QString old, QString current);
1012 bool isRecentOffset(int submode, int offset);
1013 void markOffsetRecent(int offset);
1014 bool isDirectedOffset(int offset, bool *pIsAllCall);
1015 void markOffsetDirected(int offset, bool isAllCall);
1016 void clearOffsetDirected(int offset);
1017 void processActivity(bool force = false);
1018 void resetTimeDeltaAverage();
1019 void processRxActivity();
1020 void processIdleActivity();
1021 void processCompoundActivity();
1022 void processBufferedActivity();
1023 void processCommandActivity();
1024 QString inboxPath();
1025 void refreshInboxCounts();
1026 bool hasMessageHistory(QString call);
1027 int addCommandToMyInbox(CommandDetail d);
1028 int addCommandToStorage(QString type, CommandDetail d);
1029 int getNextMessageIdForCallsign(QString callsign);
1030 int getLookaheadMessageIdForCallsign(QString callsign, int afterMsgId);
1031 int getNextGroupMessageIdForCallsign(QString group_name, QString callsign);
1032 int getLookaheadGroupMessageIdForCallsign(QString group_name,
1033 QString callsign, int afterMsgId);
1034 int countUnreadForCallsign(const QString &callsign);
1035 int countGroupUnreadForCallsign(const QString &group_name,
1036 const QString &callsign);
1037 bool markGroupMsgDeliveredForCallsign(int msgId, QString callsign);
1038 bool markMsgDelivered(int mid, Message msg);
1039 QStringList parseRelayPathCallsigns(QString from, QString text);
1040 void processSpots();
1041 void processTxQueue();
1042 void displayActivity(bool force = false);
1043 void displayBandActivity();
1044 void displayCallActivity();
1045 void enable_DXCC_entity(bool on);
1046 void setRig(Frequency = 0); // zero frequency means no change
1047 QDateTime nextTransmitCycle();
1048 void statusUpdate();
1049 void on_the_minute();
1050 void tryBandHop();
1051 void add_child_to_event_filter(QObject *);
1052 void remove_child_from_event_filter(QObject *);
1053 void setup_status_bar();
1054 QString columnLabel(QString defaultLabel);
1055 void ensureMessageDock();
1056
1057 void resetIdleTimer();
1058 void incrementIdleTimer();
1059 void tx_watchdog(bool triggered);
1060 void write_frequency_entry(QString const &file_name);
1061 void write_transmit_entry(QString const &file_name);
1062};
1063
1064#endif // MAINWINDOW_H
APRS-IS client interface for JS8Call.
Defines the inbound APRS-IS relay handler for JS8Call.
Pill-shaped visual highlights for directed message tokens.
Definition ADIF.h:18
APRS-IS client responsible for sending and receiving APRS frames.
Definition APRSISClient.h:21
Handles inbound APRS-IS messages and enqueues JS8 relays.
Definition AprsInboundRelay.h:20
Definition AudioDevice.h:11
Definition Configuration.h:57
Definition DecodedText.h:16
Definition Detector.h:15
Definition FrequencyList.h:67
Definition HelpTextWindow.h:9
Definition JS8MessageBox.h:13
Definition JS8.h:86
Definition JSC_checker.h:12
Definition LogBook.h:19
Definition LogQSO.h:22
Definition MessageClient.h:21
Definition MessagePanel.h:12
Definition MessageServer.h:14
Definition Message.h:16
Definition Modulator.h:20
Definition MultiSettings.h:62
Definition NetworkAccessManager.h:18
Definition NotificationAudio.h:13
Definition PSKReporter.h:13
Definition qpriorityqueue.h:39
Definition qpriorityqueue.h:72
Definition SoundInput.h:16
Definition SoundOutput.h:13
Definition SpotClient.h:9
Definition TCPClient.h:9
Definition Transceiver.h:83
Definition Transceiver.h:50
Definition TxLoop.h:10
void dataSink(qint64 frames)
Definition dataSink.cpp:79
void guiUpdate()
Definition mainwindow.cpp:2643
void resetMessageTransmitQueue()
Resets the frame-level transmission state after a message completes.
Definition mainwindow.cpp:3470
UI_Constructor(QString const &program_info, QDir const &temp_directory, bool multiple, MultiSettings *settings, QWidget *parent=nullptr)
Definition UI_Constructor.cpp:19
void processDecodeEvent(JS8::Event::Variant const &)
Definition processDecodeEvent.cpp:10
Definition WSJTXMessageClient.h:17
Maps JS8Call events to WSJT-X protocol messages.
Definition WSJTXMessageMapper.h:21
Definition WideGraph.h:29
Definition StationList.h:50
Definition mainwindow.h:848