From c50133bcfcb13d0bee3b68ce77ff0c29bbbe679b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 14 Oct 2020 20:59:32 +0100 Subject: [PATCH 01/73] Honour "Settings->General->Disable Tx after sending 73" if not auto-sequencing --- widgets/mainwindow.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index c83449e3b..0766b35d1 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -5747,7 +5747,8 @@ void MainWindow::on_genStdMsgsPushButton_clicked() //genStdMsgs button void MainWindow::on_logQSOButton_clicked() //Log QSO button { - if (SpecOp::FOX != m_config.special_op_id ()) + if (SpecOp::FOX != m_config.special_op_id () + && ui->cbAutoSeq->isVisible () && ui->cbAutoSeq->isEnabled () && ui->cbAutoSeq->isChecked ()) { // ensure that auto Tx is disabled even if clear DX call & grid // on 73 is not checked, unless in Fox mode where it is allowed From 8d088cf4f5e7158066c88757ebf043219a646724 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 18 Oct 2020 02:09:17 +0100 Subject: [PATCH 02/73] Repair defect with response to UDP Reply(4) messages with AP markers --- widgets/mainwindow.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 3d99e438a..1486db3e9 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -7668,13 +7668,21 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de QString format_string {"%1 %2 %3 %4 %5 %6"}; auto const& time_string = time.toString ("~" == mode || "&" == mode || "+" == mode ? "hhmmss" : "hhmm"); + auto text = message_text; + auto ap_pos = text.lastIndexOf (QRegularExpression {R"((?:\?\s)?a[0-9]$)"}); + if (ap_pos >= 0) + { + // beware of decodes ending on shorter version of wanted call so + // add a space + text = text.left (ap_pos).trimmed () + ' '; + } auto message_line = format_string .arg (time_string) .arg (snr, 3) .arg (delta_time, 4, 'f', 1) .arg (delta_frequency, 4) .arg (mode, -2) - .arg (message_text); + .arg (text); QTextCursor start {ui->decodedTextBrowser->document ()}; start.movePosition (QTextCursor::End); auto cursor = ui->decodedTextBrowser->document ()->find (message_line, start, QTextDocument::FindBackward); @@ -7687,7 +7695,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de .arg ('-' + QString::number (delta_time, 'f', 1), 4) .arg (delta_frequency, 4) .arg (mode, -2) - .arg (message_text), start, QTextDocument::FindBackward); + .arg (text), start, QTextDocument::FindBackward); } if (!cursor.isNull ()) { @@ -7702,7 +7710,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de showNormal (); raise (); } - if (message_text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"})) { + if (text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"})) { // a message we are willing to accept and auto reply to m_bDoubleClicked = true; } From ccb7a1adf5e81710958a613f8cb0d2b47b2fce7a Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 18 Oct 2020 02:09:17 +0100 Subject: [PATCH 03/73] Repair defect with response to UDP Reply(4) messages with AP markers --- widgets/mainwindow.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 0766b35d1..f11b928dd 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -7668,13 +7668,21 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de QString format_string {"%1 %2 %3 %4 %5 %6"}; auto const& time_string = time.toString ("~" == mode || "&" == mode || "+" == mode ? "hhmmss" : "hhmm"); + auto text = message_text; + auto ap_pos = text.lastIndexOf (QRegularExpression {R"((?:\?\s)?a[0-9]$)"}); + if (ap_pos >= 0) + { + // beware of decodes ending on shorter version of wanted call so + // add a space + text = text.left (ap_pos).trimmed () + ' '; + } auto message_line = format_string .arg (time_string) .arg (snr, 3) .arg (delta_time, 4, 'f', 1) .arg (delta_frequency, 4) .arg (mode, -2) - .arg (message_text); + .arg (text); QTextCursor start {ui->decodedTextBrowser->document ()}; start.movePosition (QTextCursor::End); auto cursor = ui->decodedTextBrowser->document ()->find (message_line, start, QTextDocument::FindBackward); @@ -7687,7 +7695,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de .arg ('-' + QString::number (delta_time, 'f', 1), 4) .arg (delta_frequency, 4) .arg (mode, -2) - .arg (message_text), start, QTextDocument::FindBackward); + .arg (text), start, QTextDocument::FindBackward); } if (!cursor.isNull ()) { @@ -7702,7 +7710,7 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de showNormal (); raise (); } - if (message_text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"})) { + if (text.contains (QRegularExpression {R"(^(CQ |CQDX |QRZ ))"})) { // a message we are willing to accept and auto reply to m_bDoubleClicked = true; } From 9b1695285d6f4d0e955ba70bb66e26858914dcee Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 20 Oct 2020 02:21:08 +0100 Subject: [PATCH 04/73] Compatibility with older Qt versions --- widgets/LazyFillComboBox.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/widgets/LazyFillComboBox.hpp b/widgets/LazyFillComboBox.hpp index 7d9052673..37af60f0b 100644 --- a/widgets/LazyFillComboBox.hpp +++ b/widgets/LazyFillComboBox.hpp @@ -24,6 +24,7 @@ public: { } +#if QT_VERSION >= QT_VERSION_CHECK (5, 12, 0) void showPopup () override { Q_EMIT about_to_show_popup (); @@ -35,6 +36,19 @@ public: QComboBox::hidePopup (); Q_EMIT popup_hidden (); } +#else + void mousePressEvent (QMouseEvent * e) override + { + Q_EMIT about_to_show_popup (); + QComboBox::mousePressEvent (e); + } + + void mouseReleaseEvent (QMouseEvent * e) override + { + QComboBox::mouseReleaseEvent (e); + Q_EMIT popup_hidden (); + } +#endif }; #endif From adcb0219414272d4c7ab823f1634f07a3342cd25 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 20 Oct 2020 02:21:08 +0100 Subject: [PATCH 05/73] Compatibility with older Qt versions --- widgets/LazyFillComboBox.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/widgets/LazyFillComboBox.hpp b/widgets/LazyFillComboBox.hpp index 7d9052673..37af60f0b 100644 --- a/widgets/LazyFillComboBox.hpp +++ b/widgets/LazyFillComboBox.hpp @@ -24,6 +24,7 @@ public: { } +#if QT_VERSION >= QT_VERSION_CHECK (5, 12, 0) void showPopup () override { Q_EMIT about_to_show_popup (); @@ -35,6 +36,19 @@ public: QComboBox::hidePopup (); Q_EMIT popup_hidden (); } +#else + void mousePressEvent (QMouseEvent * e) override + { + Q_EMIT about_to_show_popup (); + QComboBox::mousePressEvent (e); + } + + void mouseReleaseEvent (QMouseEvent * e) override + { + QComboBox::mouseReleaseEvent (e); + Q_EMIT popup_hidden (); + } +#endif }; #endif From 52b20848825ad06df8278a2a1aa2cc7205d5e650 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 20 Oct 2020 12:43:45 +0100 Subject: [PATCH 06/73] Update WSPRnet.org posts to allow mode to be determined The sent/received 'mode' parameter posted to WSPRnet.org has been amended as follows: WSPR-2: "2" FST4W-120: "3" FST4W-300: "5" FST4W-900: "16" FST4W-1800: "30" this change is designed to maintain backwards compatibility with older versions of WSJT-X and other software like WSPR-X which already post these values: WSPR-2: "2" WSPR-15: "15" It is expected that the WSPRnet.org server side will be updated in sync with a WSJT-X v2.3.0 RC2 (or GA) release to account for this change. --- Network/wsprnet.cpp | 38 ++++++++++++++++++++++---------------- Network/wsprnet.h | 7 ++++--- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Network/wsprnet.cpp b/Network/wsprnet.cpp index ba1e36c18..e01be1b5e 100644 --- a/Network/wsprnet.cpp +++ b/Network/wsprnet.cpp @@ -211,7 +211,7 @@ void WSPRNet::networkReply (QNetworkReply * reply) } } -bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query) +bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query) const { auto const& rx_match = wspr_re.match (line); if (rx_match.hasMatch ()) { @@ -271,7 +271,23 @@ bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query) return true; } -auto WSPRNet::urlEncodeNoSpot () -> SpotQueue::value_type +QString WSPRNet::encode_mode () const +{ + if (m_mode == "WSPR") return "2"; + if (m_mode == "WSPR-15") return "15"; + if (m_mode == "FST4W") + { + auto tr = static_cast ((TR_period_ / 60.)+.5); + if (2 == tr || 15 == tr) + { + tr += 1; // distinguish from WSPR-2 and WSPR-15 + } + return QString::number (tr); + } + return ""; +} + +auto WSPRNet::urlEncodeNoSpot () const -> SpotQueue::value_type { SpotQueue::value_type query; query.addQueryItem ("function", "wsprstat"); @@ -282,28 +298,18 @@ auto WSPRNet::urlEncodeNoSpot () -> SpotQueue::value_type query.addQueryItem ("tqrg", m_tfreq); query.addQueryItem ("dbm", m_dbm); query.addQueryItem ("version", m_vers); - if (m_mode == "WSPR") query.addQueryItem ("mode", "2"); - if (m_mode == "WSPR-15") query.addQueryItem ("mode", "15"); - if (m_mode == "FST4W") - { - query.addQueryItem ("mode", QString::number (static_cast ((TR_period_ / 60.)+.5))); - } + query.addQueryItem ("mode", encode_mode ()); return query;; } -auto WSPRNet::urlEncodeSpot (SpotQueue::value_type& query) -> SpotQueue::value_type +auto WSPRNet::urlEncodeSpot (SpotQueue::value_type& query) const -> SpotQueue::value_type { query.addQueryItem ("version", m_vers); query.addQueryItem ("rcall", m_call); query.addQueryItem ("rgrid", m_grid); query.addQueryItem ("rqrg", m_rfreq); - if (m_mode == "WSPR") query.addQueryItem ("mode", "2"); - if (m_mode == "WSPR-15") query.addQueryItem ("mode", "15"); - if (m_mode == "FST4W") - { - query.addQueryItem ("mode", QString::number (static_cast ((TR_period_ / 60.)+.5))); - } - return query; + query.addQueryItem ("mode", encode_mode ()); + return query; } void WSPRNet::work() diff --git a/Network/wsprnet.h b/Network/wsprnet.h index 29e5e58f8..a450d5827 100644 --- a/Network/wsprnet.h +++ b/Network/wsprnet.h @@ -34,9 +34,10 @@ public slots: void abortOutstandingRequests (); private: - bool decodeLine (QString const& line, SpotQueue::value_type& query); - SpotQueue::value_type urlEncodeNoSpot (); - SpotQueue::value_type urlEncodeSpot (SpotQueue::value_type& spot); + bool decodeLine (QString const& line, SpotQueue::value_type& query) const; + SpotQueue::value_type urlEncodeNoSpot () const; + SpotQueue::value_type urlEncodeSpot (SpotQueue::value_type& spot) const; + QString encode_mode () const; QNetworkAccessManager * network_manager_; QList m_outstandingRequests; From f2bbf98cbbee79405a5673e45b5ed4587e858ab6 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 20 Oct 2020 12:43:45 +0100 Subject: [PATCH 07/73] Update WSPRnet.org posts to allow mode to be determined The sent/received 'mode' parameter posted to WSPRnet.org has been amended as follows: WSPR-2: "2" FST4W-120: "3" FST4W-300: "5" FST4W-900: "16" FST4W-1800: "30" this change is designed to maintain backwards compatibility with older versions of WSJT-X and other software like WSPR-X which already post these values: WSPR-2: "2" WSPR-15: "15" It is expected that the WSPRnet.org server side will be updated in sync with a WSJT-X v2.3.0 RC2 (or GA) release to account for this change. --- Network/wsprnet.cpp | 38 ++++++++++++++++++++++---------------- Network/wsprnet.h | 7 ++++--- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Network/wsprnet.cpp b/Network/wsprnet.cpp index ba1e36c18..e01be1b5e 100644 --- a/Network/wsprnet.cpp +++ b/Network/wsprnet.cpp @@ -211,7 +211,7 @@ void WSPRNet::networkReply (QNetworkReply * reply) } } -bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query) +bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query) const { auto const& rx_match = wspr_re.match (line); if (rx_match.hasMatch ()) { @@ -271,7 +271,23 @@ bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query) return true; } -auto WSPRNet::urlEncodeNoSpot () -> SpotQueue::value_type +QString WSPRNet::encode_mode () const +{ + if (m_mode == "WSPR") return "2"; + if (m_mode == "WSPR-15") return "15"; + if (m_mode == "FST4W") + { + auto tr = static_cast ((TR_period_ / 60.)+.5); + if (2 == tr || 15 == tr) + { + tr += 1; // distinguish from WSPR-2 and WSPR-15 + } + return QString::number (tr); + } + return ""; +} + +auto WSPRNet::urlEncodeNoSpot () const -> SpotQueue::value_type { SpotQueue::value_type query; query.addQueryItem ("function", "wsprstat"); @@ -282,28 +298,18 @@ auto WSPRNet::urlEncodeNoSpot () -> SpotQueue::value_type query.addQueryItem ("tqrg", m_tfreq); query.addQueryItem ("dbm", m_dbm); query.addQueryItem ("version", m_vers); - if (m_mode == "WSPR") query.addQueryItem ("mode", "2"); - if (m_mode == "WSPR-15") query.addQueryItem ("mode", "15"); - if (m_mode == "FST4W") - { - query.addQueryItem ("mode", QString::number (static_cast ((TR_period_ / 60.)+.5))); - } + query.addQueryItem ("mode", encode_mode ()); return query;; } -auto WSPRNet::urlEncodeSpot (SpotQueue::value_type& query) -> SpotQueue::value_type +auto WSPRNet::urlEncodeSpot (SpotQueue::value_type& query) const -> SpotQueue::value_type { query.addQueryItem ("version", m_vers); query.addQueryItem ("rcall", m_call); query.addQueryItem ("rgrid", m_grid); query.addQueryItem ("rqrg", m_rfreq); - if (m_mode == "WSPR") query.addQueryItem ("mode", "2"); - if (m_mode == "WSPR-15") query.addQueryItem ("mode", "15"); - if (m_mode == "FST4W") - { - query.addQueryItem ("mode", QString::number (static_cast ((TR_period_ / 60.)+.5))); - } - return query; + query.addQueryItem ("mode", encode_mode ()); + return query; } void WSPRNet::work() diff --git a/Network/wsprnet.h b/Network/wsprnet.h index 29e5e58f8..a450d5827 100644 --- a/Network/wsprnet.h +++ b/Network/wsprnet.h @@ -34,9 +34,10 @@ public slots: void abortOutstandingRequests (); private: - bool decodeLine (QString const& line, SpotQueue::value_type& query); - SpotQueue::value_type urlEncodeNoSpot (); - SpotQueue::value_type urlEncodeSpot (SpotQueue::value_type& spot); + bool decodeLine (QString const& line, SpotQueue::value_type& query) const; + SpotQueue::value_type urlEncodeNoSpot () const; + SpotQueue::value_type urlEncodeSpot (SpotQueue::value_type& spot) const; + QString encode_mode () const; QNetworkAccessManager * network_manager_; QList m_outstandingRequests; From 4757ee4506e1e2e391e06917d8b972923199f004 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 21 Oct 2020 01:36:00 +0100 Subject: [PATCH 08/73] Adjust Windows stack and heap reservations for FST4(W) code --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c00ec9d61..7d30f7944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1170,6 +1170,11 @@ target_link_libraries (ft4sim_mult wsjt_fort wsjt_cxx) add_executable (fst4sim lib/fst4/fst4sim.f90) target_link_libraries (fst4sim wsjt_fort wsjt_cxx) +if (WIN32) + set_target_properties (fst4sim PROPERTIES + LINK_FLAGS -Wl,--stack,0x4000000,--heap,0x6000000 + ) +endif () add_executable (ldpcsim240_101 lib/fst4/ldpcsim240_101.f90) target_link_libraries (ldpcsim240_101 wsjt_fort wsjt_cxx) @@ -1432,7 +1437,7 @@ else () ) if (WIN32) set_target_properties (wsjtx PROPERTIES - LINK_FLAGS -Wl,--stack,16777216 + LINK_FLAGS -Wl,--stack,0x400000,--heap,0x20000000 ) endif () endif () From 6c077397dc13a58d511fcdca1f47166c6cc46a51 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 21 Oct 2020 01:36:00 +0100 Subject: [PATCH 09/73] Adjust Windows stack and heap reservations for FST4(W) code --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 71589a073..2158cf0dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1170,6 +1170,11 @@ target_link_libraries (ft4sim_mult wsjt_fort wsjt_cxx) add_executable (fst4sim lib/fst4/fst4sim.f90) target_link_libraries (fst4sim wsjt_fort wsjt_cxx) +if (WIN32) + set_target_properties (fst4sim PROPERTIES + LINK_FLAGS -Wl,--stack,0x4000000,--heap,0x6000000 + ) +endif () add_executable (ldpcsim240_101 lib/fst4/ldpcsim240_101.f90) target_link_libraries (ldpcsim240_101 wsjt_fort wsjt_cxx) @@ -1432,7 +1437,7 @@ else () ) if (WIN32) set_target_properties (wsjtx PROPERTIES - LINK_FLAGS -Wl,--stack,16777216 + LINK_FLAGS -Wl,--stack,0x400000,--heap,0x20000000 ) endif () endif () From a4cbde10cb6157f2a3e058b4b328e174d7c9cc2d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 21 Oct 2020 11:46:45 +0100 Subject: [PATCH 10/73] Better executable description for jt9 This maintains the sort order in the Windows Task Manager summary background applications list. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d30f7944..046a26fc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1348,7 +1348,7 @@ generate_version_info (jt9_VERSION_RESOURCES NAME jt9 BUNDLE ${PROJECT_BUNDLE_NAME} ICON ${WSJTX_ICON_FILE} - FILE_DESCRIPTION "Slow mode decoder" + FILE_DESCRIPTION "jt9 - WSJT-X slow mode decoder" ) add_executable (jt9 ${jt9_FSRCS} ${jt9_VERSION_RESOURCES}) From 5e3b931086fe625888a2f41e6a6b4b4759935848 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 21 Oct 2020 11:46:45 +0100 Subject: [PATCH 11/73] Better executable description for jt9 This maintains the sort order in the Windows Task Manager summary background applications list. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2158cf0dc..396473e84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1348,7 +1348,7 @@ generate_version_info (jt9_VERSION_RESOURCES NAME jt9 BUNDLE ${PROJECT_BUNDLE_NAME} ICON ${WSJTX_ICON_FILE} - FILE_DESCRIPTION "Slow mode decoder" + FILE_DESCRIPTION "jt9 - WSJT-X slow mode decoder" ) add_executable (jt9 ${jt9_FSRCS} ${jt9_VERSION_RESOURCES}) From e99f22a5d2573eaae46fcb50ddd159eed21a2726 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 21 Oct 2020 13:08:03 +0100 Subject: [PATCH 12/73] Revert to previous stack reservation on Windows to accommodate F/H --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 396473e84..331194711 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1437,7 +1437,7 @@ else () ) if (WIN32) set_target_properties (wsjtx PROPERTIES - LINK_FLAGS -Wl,--stack,0x400000,--heap,0x20000000 + LINK_FLAGS -Wl,--stack,0x1000000,--heap,0x20000000 ) endif () endif () From 2a2e120d7cf4f38f51ec879ddcc032510baf9721 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 21 Oct 2020 13:09:10 +0100 Subject: [PATCH 13/73] Repair invalid string references --- widgets/mainwindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index f11b928dd..64f7f4ec4 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -9117,15 +9117,15 @@ void MainWindow::write_all(QString txRx, QString message) QString msg; QString mode_string; - if (message[4]==' ') { + if (message.size () > 5 && message[4]==' ') { msg=message.mid(4,-1); } else { msg=message.mid(6,-1); } - if (message[19]=='#') { + if (message.size () > 19 && message[19]=='#') { mode_string="JT65 "; - } else if (message[19]=='@') { + } else if (message.size () > 19 && message[19]=='@') { mode_string="JT9 "; } else { mode_string=m_mode.leftJustified(6,' '); From 0f10a58b840541898270cf3a85d09ec2b2137b0f Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 01:35:40 +0100 Subject: [PATCH 14/73] Fetch LoTW Users data on start up if it is missing --- Configuration.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 5df45c543..f244ecd9f 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -1065,8 +1065,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network }); lotw_users_.set_local_file_path (writeable_data_dir_.absoluteFilePath ("lotw-user-activity.csv")); - // load the dictionary if it exists - lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), false); + // load the dictionary if it exists, fetch and load if it doesn't + lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text ()); // // validation From 8cb6fc6098b0cc0dae9b14dd65700543ddbbd465 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 01:35:40 +0100 Subject: [PATCH 15/73] Fetch LoTW Users data on start up if it is missing --- Configuration.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 5df45c543..f244ecd9f 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -1065,8 +1065,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network }); lotw_users_.set_local_file_path (writeable_data_dir_.absoluteFilePath ("lotw-user-activity.csv")); - // load the dictionary if it exists - lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), false); + // load the dictionary if it exists, fetch and load if it doesn't + lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text ()); // // validation From 99def213d2d915b264158d66b8345d20678abfbd Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 01:40:38 +0100 Subject: [PATCH 16/73] Updated URLs for recommended Windows Open SSL installers --- doc/common/links.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/common/links.adoc b/doc/common/links.adoc index ff03ebd0b..c9473c392 100644 --- a/doc/common/links.adoc +++ b/doc/common/links.adoc @@ -93,8 +93,8 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes. :sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK] :ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice] :win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages] -:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1g.msi[Win32 OpenSSL Light Package] -:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1g.msi[Win64 OpenSSL Light Package] +:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1h.msi[Win32 OpenSSL Light Package] +:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1h.msi[Win64 OpenSSL Light Package] :writelog: https://writelog.com/[Writelog] :wsjtx_group: https://groups.io/g/WSJTX[WSJTX Group] :wsjtx: https://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X] From 5df39726b6b17f1a970c80f1331495ca3f0b2bcc Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 01:40:38 +0100 Subject: [PATCH 17/73] Updated URLs for recommended Windows Open SSL installers --- doc/common/links.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/common/links.adoc b/doc/common/links.adoc index ff03ebd0b..c9473c392 100644 --- a/doc/common/links.adoc +++ b/doc/common/links.adoc @@ -93,8 +93,8 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes. :sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK] :ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice] :win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages] -:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1g.msi[Win32 OpenSSL Light Package] -:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1g.msi[Win64 OpenSSL Light Package] +:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1h.msi[Win32 OpenSSL Light Package] +:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1h.msi[Win64 OpenSSL Light Package] :writelog: https://writelog.com/[Writelog] :wsjtx_group: https://groups.io/g/WSJTX[WSJTX Group] :wsjtx: https://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X] From 308d815fb590e6223daedeebac65d6b339c18cf2 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 03:24:19 +0100 Subject: [PATCH 18/73] Add --freq-tolerance (-F) jt9 option --- lib/jt9.f90 | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/jt9.f90 b/lib/jt9.f90 index a08a20cb2..6b4368740 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -26,10 +26,10 @@ program jt9 fhigh=4000,nrxfreq=1500,ndepth=1,nexp_decode=0,nQSOProg=0 logical :: read_files = .true., tx9 = .false., display_help = .false., & bLowSidelobes = .false. - type (option) :: long_options(29) = [ & + type (option) :: long_options(30) = [ & option ('help', .false., 'h', 'Display this help message', ''), & option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), & - option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60', & + option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60', & 'SECONDS'), & option ('executable-path', .true., 'e', & 'Location of subordinate executables (KVASD) default PATH="."', & @@ -46,6 +46,8 @@ program jt9 'Lowest JT9 frequency decoded, default HERTZ=2700', 'HERTZ'), & option ('rx-frequency', .true., 'f', & 'Receive frequency offset, default HERTZ=1500', 'HERTZ'), & + option ('freq-tolerance', .true., 'F', & + 'Receive frequency tolerance, default HERTZ=20', 'HERTZ'), & option ('patience', .true., 'w', & 'FFTW3 planing patience (0-4), default PATIENCE=1', 'PATIENCE'), & option ('fft-threads', .true., 'm', & @@ -54,8 +56,8 @@ program jt9 option ('jt4', .false., '4', 'JT4 mode', ''), & option ('ft4', .false., '5', 'FT4 mode', ''), & option ('jt65', .false.,'6', 'JT65 mode', ''), & - option ('fst4', .false., '7', 'FST4 mode', ''), & - option ('fst4w', .false., 'W', 'FST4W mode', ''), & + option ('fst4', .false., '7', 'FST4 mode', ''), & + option ('fst4w', .false., 'W', 'FST4W mode', ''), & option ('ft8', .false., '8', 'FT8 mode', ''), & option ('jt9', .false., '9', 'JT9 mode', ''), & option ('qra64', .false., 'q', 'QRA64 mode', ''), & @@ -83,10 +85,11 @@ program jt9 iwspr=0 nsubmode = 0 + ntol = 20 TRperiod=60.d0 do - call getopt('hs:e:a:b:r:m:p:d:f:w:t:987654WqTL:S:H:c:G:x:g:X:Q:', & + call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:987654WqTL:S:H:c:G:x:g:X:Q:', & long_options,c,optarg,arglen,stat,offset,remain,.true.) if (stat .ne. 0) then exit @@ -113,6 +116,8 @@ program jt9 read (optarg(:arglen), *) ndepth case ('f') read (optarg(:arglen), *) nrxfreq + case ('F') + read (optarg(:arglen), *) ntol case ('L') read (optarg(:arglen), *) flow case ('S') @@ -195,6 +200,13 @@ program jt9 go to 999 endif + if (mode .eq. 241) then + ntol = min (ntol, 100) + else if (mode .eq. 74) then + ntol = 20 + else + ntol = min (ntol, 1000) + end if allocate(shared_data) nflatten=0 do iarg = offset + 1, offset + remain @@ -258,7 +270,7 @@ program jt9 shared_data%params%nfa=flow shared_data%params%nfsplit=fsplit shared_data%params%nfb=fhigh - shared_data%params%ntol=20 + shared_data%params%ntol=ntol shared_data%params%kin=64800 if(mode.eq.240) shared_data%params%kin=720000 !### 60 s periods ### shared_data%params%nzhsym=nhsym From 3888b0d0bb05db2b0b3fc4c544a00aa4afd40538 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 03:24:19 +0100 Subject: [PATCH 19/73] Add --freq-tolerance (-F) jt9 option --- lib/jt9.f90 | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/lib/jt9.f90 b/lib/jt9.f90 index a08a20cb2..6b4368740 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -26,10 +26,10 @@ program jt9 fhigh=4000,nrxfreq=1500,ndepth=1,nexp_decode=0,nQSOProg=0 logical :: read_files = .true., tx9 = .false., display_help = .false., & bLowSidelobes = .false. - type (option) :: long_options(29) = [ & + type (option) :: long_options(30) = [ & option ('help', .false., 'h', 'Display this help message', ''), & option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), & - option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60', & + option ('tr-period', .true., 'p', 'Tx/Rx period, default SECONDS=60', & 'SECONDS'), & option ('executable-path', .true., 'e', & 'Location of subordinate executables (KVASD) default PATH="."', & @@ -46,6 +46,8 @@ program jt9 'Lowest JT9 frequency decoded, default HERTZ=2700', 'HERTZ'), & option ('rx-frequency', .true., 'f', & 'Receive frequency offset, default HERTZ=1500', 'HERTZ'), & + option ('freq-tolerance', .true., 'F', & + 'Receive frequency tolerance, default HERTZ=20', 'HERTZ'), & option ('patience', .true., 'w', & 'FFTW3 planing patience (0-4), default PATIENCE=1', 'PATIENCE'), & option ('fft-threads', .true., 'm', & @@ -54,8 +56,8 @@ program jt9 option ('jt4', .false., '4', 'JT4 mode', ''), & option ('ft4', .false., '5', 'FT4 mode', ''), & option ('jt65', .false.,'6', 'JT65 mode', ''), & - option ('fst4', .false., '7', 'FST4 mode', ''), & - option ('fst4w', .false., 'W', 'FST4W mode', ''), & + option ('fst4', .false., '7', 'FST4 mode', ''), & + option ('fst4w', .false., 'W', 'FST4W mode', ''), & option ('ft8', .false., '8', 'FT8 mode', ''), & option ('jt9', .false., '9', 'JT9 mode', ''), & option ('qra64', .false., 'q', 'QRA64 mode', ''), & @@ -83,10 +85,11 @@ program jt9 iwspr=0 nsubmode = 0 + ntol = 20 TRperiod=60.d0 do - call getopt('hs:e:a:b:r:m:p:d:f:w:t:987654WqTL:S:H:c:G:x:g:X:Q:', & + call getopt('hs:e:a:b:r:m:p:d:f:F:w:t:987654WqTL:S:H:c:G:x:g:X:Q:', & long_options,c,optarg,arglen,stat,offset,remain,.true.) if (stat .ne. 0) then exit @@ -113,6 +116,8 @@ program jt9 read (optarg(:arglen), *) ndepth case ('f') read (optarg(:arglen), *) nrxfreq + case ('F') + read (optarg(:arglen), *) ntol case ('L') read (optarg(:arglen), *) flow case ('S') @@ -195,6 +200,13 @@ program jt9 go to 999 endif + if (mode .eq. 241) then + ntol = min (ntol, 100) + else if (mode .eq. 74) then + ntol = 20 + else + ntol = min (ntol, 1000) + end if allocate(shared_data) nflatten=0 do iarg = offset + 1, offset + remain @@ -258,7 +270,7 @@ program jt9 shared_data%params%nfa=flow shared_data%params%nfsplit=fsplit shared_data%params%nfb=fhigh - shared_data%params%ntol=20 + shared_data%params%ntol=ntol shared_data%params%kin=64800 if(mode.eq.240) shared_data%params%kin=720000 !### 60 s periods ### shared_data%params%nzhsym=nhsym From 5efe448a9ca0d60648a058c74e512eed98f44d49 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 03:32:22 +0100 Subject: [PATCH 20/73] Cosmetic change --- lib/jt9.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jt9.f90 b/lib/jt9.f90 index 6b4368740..81013f1b6 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -202,7 +202,7 @@ program jt9 if (mode .eq. 241) then ntol = min (ntol, 100) - else if (mode .eq. 74) then + else if (mode .eq. 65 + 9) then ntol = 20 else ntol = min (ntol, 1000) From c0f11fb67b7f5d54faba8185a157055706f70b60 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 04:36:28 +0100 Subject: [PATCH 21/73] Repair regression with UDP spotting to PSK Reporter Recover correctly from broken connections, i.e. do nothing for UDP. --- Network/PSKReporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Network/PSKReporter.cpp b/Network/PSKReporter.cpp index 8c8d7948d..35c56f23f 100644 --- a/Network/PSKReporter.cpp +++ b/Network/PSKReporter.cpp @@ -84,7 +84,7 @@ public: { if (!socket_ || QAbstractSocket::UnconnectedState == socket_->state () - || (socket_->socketType () != config_->psk_reporter_tcpip () ? QAbstractSocket::TcpSocket : QAbstractSocket::UdpSocket)) + || (socket_->socketType () != (config_->psk_reporter_tcpip () ? QAbstractSocket::TcpSocket : QAbstractSocket::UdpSocket))) { // we need to create the appropriate socket if (socket_ From ab90585e46c166e09c45808cefb719a9edc379f2 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 03:32:22 +0100 Subject: [PATCH 22/73] Cosmetic change --- lib/jt9.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/jt9.f90 b/lib/jt9.f90 index 6b4368740..81013f1b6 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -202,7 +202,7 @@ program jt9 if (mode .eq. 241) then ntol = min (ntol, 100) - else if (mode .eq. 74) then + else if (mode .eq. 65 + 9) then ntol = 20 else ntol = min (ntol, 1000) From 66e9102d6717e0adf2ad70d94de0d9ec1b293f5e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 23 Oct 2020 04:36:28 +0100 Subject: [PATCH 23/73] Repair regression with UDP spotting to PSK Reporter Recover correctly from broken connections, i.e. do nothing for UDP. --- Network/PSKReporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Network/PSKReporter.cpp b/Network/PSKReporter.cpp index 8c8d7948d..35c56f23f 100644 --- a/Network/PSKReporter.cpp +++ b/Network/PSKReporter.cpp @@ -84,7 +84,7 @@ public: { if (!socket_ || QAbstractSocket::UnconnectedState == socket_->state () - || (socket_->socketType () != config_->psk_reporter_tcpip () ? QAbstractSocket::TcpSocket : QAbstractSocket::UdpSocket)) + || (socket_->socketType () != (config_->psk_reporter_tcpip () ? QAbstractSocket::TcpSocket : QAbstractSocket::UdpSocket))) { // we need to create the appropriate socket if (socket_ From 731fe53a1ec70229606399bf8f9c11cc05518223 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 26 Oct 2020 20:20:52 +0000 Subject: [PATCH 24/73] Reasonable default values for NB setting for command line jt9 Use the -X command option to set single decode mode and to set the NB level. -X 256*(n+3)+s Where s=32 selects single decode mode, and 'n' is the equivalent NB setting as used in the WSJT-X UI. Default for both is zero in FST4(W) mode if no -X option is passed. E.g. -X 544 selects single decode with NB=-1 (256*(-1+3)+32). --- lib/jt9.f90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/jt9.f90 b/lib/jt9.f90 index 81013f1b6..77ad5b9fd 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -25,7 +25,7 @@ program jt9 integer :: arglen,stat,offset,remain,mode=0,flow=200,fsplit=2700, & fhigh=4000,nrxfreq=1500,ndepth=1,nexp_decode=0,nQSOProg=0 logical :: read_files = .true., tx9 = .false., display_help = .false., & - bLowSidelobes = .false. + bLowSidelobes = .false., nexp_decode_set = .false. type (option) :: long_options(30) = [ & option ('help', .false., 'h', 'Display this help message', ''), & option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), & @@ -158,6 +158,7 @@ program jt9 read (optarg(:arglen), *) hisgrid case ('X') read (optarg(:arglen), *) nexp_decode + nexp_decode_set = .true. end select end do @@ -207,6 +208,11 @@ program jt9 else ntol = min (ntol, 1000) end if + if (.not. nexp_decode_set) then + if (mode .eq. 240 .or. mode .eq. 241) then + nexp_decode = 3 * 256 ! single decode off and nb=0 + end if + end if allocate(shared_data) nflatten=0 do iarg = offset + 1, offset + remain From befbaa6ae9902e533b6ae52be31a5404b476f134 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 26 Oct 2020 20:20:52 +0000 Subject: [PATCH 25/73] Reasonable default values for NB setting for command line jt9 Use the -X command option to set single decode mode and to set the NB level. -X 256*(n+3)+s Where s=32 selects single decode mode, and 'n' is the equivalent NB setting as used in the WSJT-X UI. Default for both is zero in FST4(W) mode if no -X option is passed. E.g. -X 544 selects single decode with NB=-1 (256*(-1+3)+32). --- lib/jt9.f90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/jt9.f90 b/lib/jt9.f90 index 81013f1b6..77ad5b9fd 100644 --- a/lib/jt9.f90 +++ b/lib/jt9.f90 @@ -25,7 +25,7 @@ program jt9 integer :: arglen,stat,offset,remain,mode=0,flow=200,fsplit=2700, & fhigh=4000,nrxfreq=1500,ndepth=1,nexp_decode=0,nQSOProg=0 logical :: read_files = .true., tx9 = .false., display_help = .false., & - bLowSidelobes = .false. + bLowSidelobes = .false., nexp_decode_set = .false. type (option) :: long_options(30) = [ & option ('help', .false., 'h', 'Display this help message', ''), & option ('shmem',.true.,'s','Use shared memory for sample data','KEY'), & @@ -158,6 +158,7 @@ program jt9 read (optarg(:arglen), *) hisgrid case ('X') read (optarg(:arglen), *) nexp_decode + nexp_decode_set = .true. end select end do @@ -207,6 +208,11 @@ program jt9 else ntol = min (ntol, 1000) end if + if (.not. nexp_decode_set) then + if (mode .eq. 240 .or. mode .eq. 241) then + nexp_decode = 3 * 256 ! single decode off and nb=0 + end if + end if allocate(shared_data) nflatten=0 do iarg = offset + 1, offset + remain From 2b40da70cb2a8941b1e925200a631e65fcebe9f7 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 28 Oct 2020 22:06:08 +0000 Subject: [PATCH 26/73] Initial check in of a recipe to prepare to build WSJT-X on MS Windows. --- doc/building on MS Windows.txt | 73 ++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 doc/building on MS Windows.txt diff --git a/doc/building on MS Windows.txt b/doc/building on MS Windows.txt new file mode 100644 index 000000000..043e4aac6 --- /dev/null +++ b/doc/building on MS Windows.txt @@ -0,0 +1,73 @@ +Building WSJT-X on MS Windows +============================= + +Here I describe my set up, you may have other preferences due to your +favoured file system layout for tools, utilities, and libraries. Many +variations are possible, use this guide as a template. The aim is to +provide an environment suitable for general development. + +Prerequisite Tools and Libraries +================================ + +Here is an overview list, details are filled out below: + + * Qt Open Source Framework + * Cmake build system generator + * FFTW v3 DFT library + * libusb usb device library + * MSYS2 *nix like command line environment + * Hamlib rig control library + * Boost C++ libraries + +Qt Framework +------------ + +At the time of writing I recommend using Qt v5.15.0 64-bit, v5.15.1 +has a defect that affects us so is best avoided. You need the MinGW +version as we do not support the MSVC version due to lack of a +suitable FOSS Fortran complier. To install the Qt developer SDK you +should download the official Qt on-line installer, this allows you to +install one or more variants of the Qt SDK and also to maintain and +update the installation at a later date. There are many versions and +components within versions available, you only need the base 64-bit +MinGW framework for Qt v5.15.0, other components can unchecked within +the on-line installer. The default install location is C:\Qt which is +fine, do not attempt to move the location of the installed libraries +if you decide you want it elsewhere, the installer patches the +libraries for the installed location and it is easier to un-install +and re-install if you wish to change the installed location. + +CMake +----- + +Download and install a recent version from the official CMake web +site. A default installation is fine. I am currently using v3.18.3, +versions as old as v3.9 should work. + +Other tools and libraries without installers +-------------------------------------------- + +For small libraries that don't have a Windows installer and change +often I locate them under a directory C:\Tools. This location is +arbitrary and just used to aggregate such items in one place, but this +document assumes that location so you may need to adjust paths etc. if +you use a different location. + +FFTW v3 DFT library +------------------- + +The MS Windows builds of FFTW3 can be downloaded from +http://www.fftw.org/install/windows.html and unzipped into C:\Tools. +You only need the 64-bit package. + +libusb library +-------------- + +This library is available from https://libusb.info/, unzip this +package into C:\Tools. + +MSYS2 +----- + +This utility is available from https://www.msys2.org/. Follow the +download and installation instructions there. From 6f2449f510dc852ca3dfdaf1f5cb9f2fe0f6af8c Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 28 Oct 2020 23:32:49 +0000 Subject: [PATCH 27/73] Doc updates --- doc/building on MS Windows.txt | 35 +++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/doc/building on MS Windows.txt b/doc/building on MS Windows.txt index 043e4aac6..8bae6a658 100644 --- a/doc/building on MS Windows.txt +++ b/doc/building on MS Windows.txt @@ -30,12 +30,13 @@ should download the official Qt on-line installer, this allows you to install one or more variants of the Qt SDK and also to maintain and update the installation at a later date. There are many versions and components within versions available, you only need the base 64-bit -MinGW framework for Qt v5.15.0, other components can unchecked within -the on-line installer. The default install location is C:\Qt which is -fine, do not attempt to move the location of the installed libraries -if you decide you want it elsewhere, the installer patches the -libraries for the installed location and it is easier to un-install -and re-install if you wish to change the installed location. +MinGW framework for Qt v5.15.0 and the matching MinGW 8.1.0 64-bit +developer tools, other components can be unchecked within the on-line +installer. The default install location is C:\Qt which is fine, do +not attempt to move the location of the installed libraries if you +decide you want it elsewhere, the installer patches the libraries for +the installed location and it is easier to un-install and re-install +if you wish to change the installed location. CMake ----- @@ -70,4 +71,24 @@ MSYS2 ----- This utility is available from https://www.msys2.org/. Follow the -download and installation instructions there. +download, installation, and initial upgrading instructions there. Once +installed and updated you will need to install some packages, these +are needed to provide the necessary *nix tools and utilities to build +Hamlib from sources. + +Hamlib +------ + +Currently we statically link Hamlib to avoid clashes with +pre-installed DLLs that may be older versions than we support. Once +Hamlib v1.4 is officially released and commonly available we will move +to dynamic linking. Until then Hamlib must be built from +sources. There is a fork of the official Hamlib project which we keep +up to date with the official project master branch, we recommend +building from the 'integration' branch of that fork. The fork is a git +repository which can be cloned with this command: + +git clone git://git.code.sf.net/u/bsomervi/hamlib hamlib +cd hamlib +git checkout integration + From 072da278eeecc332a06b1f1960708b25c1e40201 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 29 Oct 2020 22:40:19 +0000 Subject: [PATCH 28/73] Documentation updates --- doc/building on MS Windows.txt | 85 ++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/doc/building on MS Windows.txt b/doc/building on MS Windows.txt index 8bae6a658..9e954285c 100644 --- a/doc/building on MS Windows.txt +++ b/doc/building on MS Windows.txt @@ -17,6 +17,7 @@ Here is an overview list, details are filled out below: * libusb usb device library * MSYS2 *nix like command line environment * Hamlib rig control library + * Pkg Config Lite * Boost C++ libraries Qt Framework @@ -64,8 +65,9 @@ You only need the 64-bit package. libusb library -------------- -This library is available from https://libusb.info/, unzip this -package into C:\Tools. +This library is available from https://libusb.info/, download the .7z +archive as the .zip archive does not contain the libraries we +require. Unzip this package into C:\Tools. MSYS2 ----- @@ -76,6 +78,8 @@ installed and updated you will need to install some packages, these are needed to provide the necessary *nix tools and utilities to build Hamlib from sources. + pacman -S autoconf automake libtool make + Hamlib ------ @@ -88,7 +92,78 @@ up to date with the official project master branch, we recommend building from the 'integration' branch of that fork. The fork is a git repository which can be cloned with this command: -git clone git://git.code.sf.net/u/bsomervi/hamlib hamlib -cd hamlib -git checkout integration + mkdir -p ~/src/sf/bsomervi + cd !$ + git clone git://git.code.sf.net/u/bsomervi/hamlib hamlib + cd hamlib + git checkout integration + +Next you must build Hamlib using the MinGW compiler tools bundled with +Qt. As you will build Hamlib again when there are updates you should +set up you Msys2 command line environment for this. I use a +$HOME/.bash_profile file containing these lines: + + dll_paths_64bit=/c/Tools/libusb-1.0.23/MinGW64/dll + export PATH=/c/Qt/Tools/mingw810_64/bin:$dll_paths_64bit:$PATH + +Test the amended ~/.bash_profile file by opening a new Msys2 shell and +typing: + + which gcc + which libusb-1.0.dll + +The first time you checkout the Hamlib sources you must bootstrap the +configuration script, this is done with a script at the root of the +Hamlib sources: + + cd ~/src/sf/bsomervi/hamlib + ./bootstrap + +Now you need to configure and build Hamlib from an Msys2 shell. Create +a build directory outside of the Hamlib sources you have just cloned, +then change working directory to that build directory. + + mkdir -p ~/build/hamlib/release + cd !$ + ~/src/sf/bsomervi/hamlib/configure --disable-shared \ + --prefix=$HOME/local/hamlib/mingw64/release \ + CFLAGS="-DNDEBUG -g -O2 -fdata-sections -ffunction-sections -I/c/Tools/libusb-1.0.23/include" \ + CXXFLAGS="-DNDEBUG -g -O2 -fdata-sections -ffunction-sections" \ + LDFLAGS="-Wl,--gc-sections" \ + LIBUSB_LIBS="-L/c/Tools/libusb-1.0.23/MinGW64/dll -lusb-1.0" + +Then build and install the Hamlib package into a local directory: + + make & make install-strip + +If you wish you can make a debug configuration build of Hamlib which +can be useful if you intended to contribute to the Hamlib project, or +for tracking down issues: + + mkdir -p ~/build/hamlib/debug + cd !$ + ~/src/sf/bsomervi/hamlib/configure --disable-shared \ + --prefix=$HOME/local/hamlib/mingw64/debug \ + CFLAGS="-g -O0 -I/c/Tools/libusb-1.0.23/include" \ + CXXFLAGS="-g -O0" \ + LIBUSB_LIBS="-L/c/Tools/libusb-1.0.23/MinGW64/dll -lusb-1.0" + make && make install + +To update the Hamlib sources to the latest commit and rebuild: + + cd ~/src/sf/bsomervi/hamlib + git pull + cd ~/build/hamlib/release + make & make install-strip + cd ~/build/hamlib/debug + make && make install + +Pkg Config Lite +--------------- + +This package allows the WSJT-X CMake configuration to locate and learn +the options needed to consume the Hamlib package. You can download it +from https://sourceforge.net/projects/pkgconfiglite/files/0.28-1/ and +unzip it into a convenient location, as with other ancillary tools and +libraries I put these under C:\Tools\. From 430d57c1cad9e66ca901c51e414cb60dd5742dec Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 2 Nov 2020 15:33:44 +0000 Subject: [PATCH 29/73] Network interface selection for outgoing UDP multicast datagrams Default selection is the loop-back interface. Users who require interoperation between WSJT-X instances cooperating applications running on different hosts should select a suitable network interface and carefully choose a multicast group address, and TTL, that has minimal scope covering the necessary network(s). Using 224.0.0.1 is a reasonable strategy if all hosts are on the same subnet. Administratively scoped multicast group addresses like those within 239.255.0.0/16 can cover larger boundaries, but care must be taken if the local subnet has access to a multicast enabled router. The IPv4 broadcast address (255.255.255.255) may be used as an alternative to multicast UDP, but note that WSJT-X will only send broadcast UDP datagrams on the loop-back interface, so all recipient applications must be running on the same host system. The reference UDP Message protocol applications are being extended to be configurable with a list of interfaces to join a multicast group address on. By default they will only join on the loop-back interface, which is also recommended for any applications designed to take part in the WSJT-X UDP Message Protocol. This allows full user control of the scope of multicast group membership with a very conservative default mode that will work with all interoperating applications running on the same host system. --- Configuration.cpp | 159 +++++++++++++++++++++++++++- Configuration.hpp | 6 +- Configuration.ui | 61 ++++++++--- Network/MessageClient.cpp | 193 ++++++++++++++++++++++++---------- Network/MessageClient.hpp | 15 ++- UDPExamples/MessageServer.cpp | 85 +++++++-------- UDPExamples/MessageServer.hpp | 7 +- UDPExamples/UDPDaemon.cpp | 19 +++- qt_helpers.hpp | 26 +++++ tests/test_qt_helpers.cpp | 74 +++++++++++++ widgets/mainwindow.cpp | 4 +- 11 files changed, 510 insertions(+), 139 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index f244ecd9f..fac5564ab 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -163,6 +163,9 @@ #include #include #include +#include +#include +#include #include #include "pimpl_impl.hpp" @@ -439,6 +442,10 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); + void load_network_interfaces (QComboBox *, QString const& current); + Q_SLOT void host_info_results (QHostInfo); + void check_multicast (QHostAddress const&); + void find_tab (QWidget *); void initialize_models (); @@ -492,6 +499,8 @@ private: Q_SLOT void on_add_macro_line_edit_editingFinished (); Q_SLOT void delete_macro (); void delete_selected_macros (QModelIndexList); + Q_SLOT void on_udp_server_line_edit_textChanged (QString const&); + Q_SLOT void on_udp_server_line_edit_editingFinished (); Q_SLOT void on_save_path_select_push_button_clicked (bool); Q_SLOT void on_azel_path_select_push_button_clicked (bool); Q_SLOT void on_calibration_intercept_spin_box_valueChanged (double); @@ -641,7 +650,11 @@ private: bool use_dynamic_grid_; QString opCall_; QString udp_server_name_; + bool udp_server_name_edited_; + int dns_lookup_id_; port_type udp_server_port_; + QString udp_interface_name_; + int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; bool broadcast_to_n1mm_; @@ -741,6 +754,8 @@ QString Configuration::opCall() const {return m_->opCall_;} void Configuration::opCall (QString const& call) {m_->opCall_ = call;} QString Configuration::udp_server_name () const {return m_->udp_server_name_;} auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;} +QString Configuration::udp_interface_name () const {return m_->udp_interface_name_;} +int Configuration::udp_TTL () const {return m_->udp_TTL_;} bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;} QString Configuration::n1mm_server_name () const {return m_->n1mm_server_name_;} auto Configuration::n1mm_server_port () const -> port_type {return m_->n1mm_server_port_;} @@ -995,6 +1010,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network , transceiver_command_number_ {0} , degrade_ {0.} // initialize to zero each run, not // saved in settings + , udp_server_name_edited_ {false} + , dns_lookup_id_ {-1} { ui_->setupUi (this); @@ -1044,6 +1061,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network // this must be done after the default paths above are set read_settings (); + // set up dynamic loading of audio devices connect (ui_->sound_input_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor}); load_audio_devices (QAudio::AudioInput, ui_->sound_input_combo_box, &next_audio_input_device_); @@ -1059,6 +1077,13 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network QGuiApplication::restoreOverrideCursor (); }); + // set up dynamic loading of network interfaces + connect (ui_->udp_interface_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { + QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor}); + load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); + QGuiApplication::restoreOverrideCursor (); + }); + // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { ui_->LotW_CSV_fetch_push_button->setEnabled (true); @@ -1335,7 +1360,14 @@ void Configuration::impl::initialize_models () ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval); ui_->opCallEntry->setText (opCall_); ui_->udp_server_line_edit->setText (udp_server_name_); + on_udp_server_line_edit_editingFinished (); ui_->udp_server_port_spin_box->setValue (udp_server_port_); + load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); + if (!udp_interface_name_.size ()) + { + udp_interface_name_ = ui_->udp_interface_combo_box->currentData ().toString (); + } + ui_->udp_TTL_spin_box->setValue (udp_TTL_); ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_); ui_->n1mm_server_name_line_edit->setText (n1mm_server_name_); ui_->n1mm_server_port_spin_box->setValue (n1mm_server_port_); @@ -1513,6 +1545,8 @@ void Configuration::impl::read_settings () rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value (); opCall_ = settings_->value ("OpCall", "").toString (); udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString (); + udp_interface_name_ = settings_->value ("UDPInterface").toString (); + udp_TTL_ = settings_->value ("UDPTTL").toInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString (); n1mm_server_port_ = settings_->value ("N1MMServerPort", 2333).toUInt (); @@ -1641,6 +1675,8 @@ void Configuration::impl::write_settings () settings_->setValue ("OpCall", opCall_); settings_->setValue ("UDPServer", udp_server_name_); settings_->setValue ("UDPServerPort", udp_server_port_); + settings_->setValue ("UDPInterface", udp_interface_name_); + settings_->setValue ("UDPTTL", udp_TTL_); settings_->setValue ("N1MMServer", n1mm_server_name_); settings_->setValue ("N1MMServerPort", n1mm_server_port_); settings_->setValue ("BroadcastToN1MM", broadcast_to_n1mm_); @@ -1843,6 +1879,12 @@ bool Configuration::impl::validate () return false; } + if (dns_lookup_id_ > -1) + { + MessageBox::information_message (this, tr ("Pending DNS lookup, please try again later")); + return false; + } + return true; } @@ -2061,20 +2103,30 @@ void Configuration::impl::accept () pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked (); pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked (); opCall_=ui_->opCallEntry->text(); - auto new_server = ui_->udp_server_line_edit->text (); - if (new_server != udp_server_name_) + + auto new_server = ui_->udp_server_line_edit->text ().trimmed (); + auto new_interface = ui_->udp_interface_combo_box->currentData ().toString (); + if (new_server != udp_server_name_ || new_interface != udp_interface_name_) { udp_server_name_ = new_server; - Q_EMIT self_->udp_server_changed (new_server); + udp_interface_name_ = new_interface; + Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_name_); } auto new_port = ui_->udp_server_port_spin_box->value (); if (new_port != udp_server_port_) { udp_server_port_ = new_port; - Q_EMIT self_->udp_server_port_changed (new_port); + Q_EMIT self_->udp_server_port_changed (udp_server_port_); } - + + auto new_TTL = ui_->udp_TTL_spin_box->value (); + if (new_TTL != udp_TTL_) + { + udp_TTL_ = new_TTL; + Q_EMIT self_->udp_TTL_changed (udp_TTL_); + } + if (ui_->accept_udp_requests_check_box->isChecked () != accept_udp_requests_) { accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked (); @@ -2130,6 +2182,12 @@ void Configuration::impl::accept () void Configuration::impl::reject () { + if (dns_lookup_id_ > -1) + { + QHostInfo::abortHostLookup (dns_lookup_id_); + dns_lookup_id_ = -1; + } + initialize_models (); // reverts to settings as at exec () // check if the Transceiver instance changed, in which case we need @@ -2344,6 +2402,72 @@ void Configuration::impl::on_add_macro_push_button_clicked (bool /* checked */) } } +void Configuration::impl::on_udp_server_line_edit_textChanged (QString const&) +{ + udp_server_name_edited_ = true; +} + +void Configuration::impl::on_udp_server_line_edit_editingFinished () +{ + if (udp_server_name_edited_) + { + auto const& server = ui_->udp_server_line_edit->text ().trimmed (); + QHostAddress ha {server}; + if (server.size () && ha.isNull ()) + { + // queue a host address lookup + qDebug () << "server host DNS lookup:" << server; +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + dns_lookup_id_ = QHostInfo::lookupHost (server, this, &Configuration::impl::host_info_results); +#else + dns_lookup_id_ = QHostInfo::lookupHost (server, this, SLOT (host_info_results (QHostInfo))); +#endif + } + else + { + check_multicast (ha); + } + } +} + +void Configuration::impl::host_info_results (QHostInfo host_info) +{ + if (host_info.lookupId () != dns_lookup_id_) return; + dns_lookup_id_ = -1; + if (QHostInfo::NoError != host_info.error ()) + { + MessageBox::critical_message (this, tr ("UDP server DNS lookup failed"), host_info.errorString ()); + } + else + { + auto const& server_addresses = host_info.addresses (); + qDebug () << "message server addresses:" << server_addresses; + if (server_addresses.size ()) + { + check_multicast (server_addresses[0]); + } + } +} + +void Configuration::impl::check_multicast (QHostAddress const& ha) +{ + auto is_multicast = is_multicast_address (ha); + ui_->udp_interface_label->setVisible (is_multicast); + ui_->udp_interface_combo_box->setVisible (is_multicast); + ui_->udp_TTL_label->setVisible (is_multicast); + ui_->udp_TTL_spin_box->setVisible (is_multicast); + if (isVisible ()) + { + if (is_MAC_ambiguous_multicast_address (ha)) + { + MessageBox::warning_message (this, tr ("MAC-ambiguous multicast groups addresses not supported")); + find_tab (ui_->udp_server_line_edit); + ui_->udp_server_line_edit->clear (); + } + } + udp_server_name_edited_ = false; +} + void Configuration::impl::delete_frequencies () { auto selection_model = ui_->frequencies_table_view->selectionModel (); @@ -2868,6 +2992,31 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com combo_box->setCurrentIndex (current_index); } +// load the available network interfaces into the selection combo box +void Configuration::impl::load_network_interfaces (QComboBox * combo_box, QString const& current) +{ + combo_box->clear (); + int current_index = -1; + for (auto const& interface : QNetworkInterface::allInterfaces ()) + { + if (interface.flags () & QNetworkInterface::IsUp) + { + auto const& name = interface.name (); + combo_box->addItem (interface.humanReadableName (), name); + // select the first loopback interface as a default to + // discourage spamming the network (possibly the Internet), + // particularly important with administratively scoped + // multicast UDP + if (name == current + || (!current.size () && (interface.flags () & QNetworkInterface::IsLoopBack))) + { + current_index = combo_box->count () - 1; + } + } + } + combo_box->setCurrentIndex (current_index); +} + // enable only the channels that are supported by the selected audio device void Configuration::impl::update_audio_channels (QComboBox const * source_combo_box, int index, QComboBox * combo_box, bool allow_both) { diff --git a/Configuration.hpp b/Configuration.hpp index 8594a4a6f..403673663 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -21,7 +21,6 @@ class Bands; class FrequencyList_v2; class StationList; class QStringListModel; -class QHostAddress; class LotWUsers; class DecodeHighlightingModel; class LogBook; @@ -152,6 +151,8 @@ public: void opCall (QString const&); QString udp_server_name () const; port_type udp_server_port () const; + QString udp_interface_name () const; + int udp_TTL () const; QString n1mm_server_name () const; port_type n1mm_server_port () const; bool valid_n1mm_info () const; @@ -273,8 +274,9 @@ public: // // This signal is emitted when the UDP server changes // - Q_SIGNAL void udp_server_changed (QString const& udp_server) const; + Q_SIGNAL void udp_server_changed (QString& udp_server_name, QString const& network_interface) const; Q_SIGNAL void udp_server_port_changed (port_type server_port) const; + Q_SIGNAL void udp_TTL_changed (int TTL) const; Q_SIGNAL void accept_udp_requests_changed (bool checked) const; // signal updates to decode highlighting diff --git a/Configuration.ui b/Configuration.ui index fbd53c422..fd8fb8955 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -7,7 +7,7 @@ 0 0 554 - 556 + 560 @@ -1864,12 +1864,6 @@ and DX Grid fields when a 73 or free text message is sent. - - - 0 - 0 - - <html><head/><body><p>Optional hostname of network service to receive decodes.</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable the broadcasting of UDP status updates.</p></body></html> @@ -1898,6 +1892,39 @@ and DX Grid fields when a 73 or free text message is sent. + + + + Outgoing interface: + + + udp_interface_combo_box + + + + + + + + + + 255 + + + 1 + + + + + + + Multicast TTL: + + + udp_TTL_spin_box + + + @@ -3084,6 +3111,8 @@ Right click for insert and delete options. psk_reporter_tcpip_check_box udp_server_line_edit udp_server_port_spin_box + udp_interface_combo_box + udp_TTL_spin_box accept_udp_requests_check_box udpWindowToFront udpWindowRestore @@ -3101,8 +3130,8 @@ Right click for insert and delete options. include_WAE_check_box rescan_log_push_button LotW_CSV_URL_line_edit - LotW_days_since_upload_spin_box LotW_CSV_fetch_push_button + LotW_days_since_upload_spin_box sbNtrials sbAggressive cbTwoPass @@ -3118,11 +3147,11 @@ Right click for insert and delete options. rbHound rbNA_VHF_Contest rbField_Day - Field_Day_Exchange rbEU_VHF_Contest rbRTTY_Roundup - RTTY_Exchange rbWW_DIGI + Field_Day_Exchange + RTTY_Exchange @@ -3192,13 +3221,13 @@ Right click for insert and delete options. - - - - - - + + + + + + diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 3c208fd3f..57ffb2806 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -6,16 +6,16 @@ #include #include +#include #include #include #include #include -#include #include #include #include "NetworkMessage.hpp" - +#include "qt_helpers.hpp" #include "pimpl_impl.hpp" #include "moc_MessageClient.cpp" @@ -34,14 +34,15 @@ class MessageClient::impl public: impl (QString const& id, QString const& version, QString const& revision, - port_type server_port, MessageClient * self) + port_type server_port, int TTL, MessageClient * self) : self_ {self} - , dns_lookup_id_ {0} , enabled_ {false} , id_ {id} , version_ {version} , revision_ {revision} + , dns_lookup_id_ {-1} , server_port_ {server_port} + , TTL_ {TTL} , schema_ {2} // use 2 prior to negotiation not 1 which is broken , heartbeat_timer_ {new QTimer {this}} { @@ -49,9 +50,6 @@ public: connect (this, &QIODevice::readyRead, this, &impl::pending_datagrams); heartbeat_timer_->start (NetworkMessage::pulse * 1000); - - // bind to an ephemeral port - bind (); } ~impl () @@ -61,7 +59,10 @@ public: enum StreamStatus {Fail, Short, OK}; - void parse_message (QByteArray const& msg); + void set_server (QString const& server_name, QString const& network_interface_name); + Q_SLOT void host_info_results (QHostInfo); + void start (); + void parse_message (QByteArray const&); void pending_datagrams (); void heartbeat (); void closedown (); @@ -69,27 +70,26 @@ public: void send_message (QByteArray const&); void send_message (QDataStream const& out, QByteArray const& message) { - if (OK == check_status (out)) - { - send_message (message); - } - else - { - Q_EMIT self_->error ("Error creating UDP message"); - } + if (OK == check_status (out)) + { + send_message (message); + } + else + { + Q_EMIT self_->error ("Error creating UDP message"); + } } - Q_SLOT void host_info_results (QHostInfo); - MessageClient * self_; - int dns_lookup_id_; bool enabled_; QString id_; QString version_; QString revision_; - QString server_string_; - port_type server_port_; + int dns_lookup_id_; QHostAddress server_; + port_type server_port_; + int TTL_; + QNetworkInterface network_interface_; quint32 schema_; QTimer * heartbeat_timer_; std::vector blocked_addresses_; @@ -101,37 +101,117 @@ public: #include "MessageClient.moc" +void MessageClient::impl::set_server (QString const& server_name, QString const& network_interface_name) +{ + server_.setAddress (server_name); + network_interface_ = QNetworkInterface::interfaceFromName (network_interface_name); + if (server_.isNull () && server_name.size ()) // DNS lookup required + { + // queue a host address lookup +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + dns_lookup_id_ = QHostInfo::lookupHost (server_name, this, &MessageClient::impl::host_info_results); +#else + dns_lookup_id_ = QHostInfo::lookupHost (server_name, this, SLOT (host_info_results (QHostInfo))); +#endif + } + else + { + start (); + } +} + void MessageClient::impl::host_info_results (QHostInfo host_info) { if (host_info.lookupId () != dns_lookup_id_) return; + dns_lookup_id_ = -1; if (QHostInfo::NoError != host_info.error ()) { - Q_EMIT self_->error ("UDP server lookup failed:\n" + host_info.errorString ()); - pending_messages_.clear (); // discard + Q_EMIT self_->error ("UDP server DNS lookup failed: " + host_info.errorString ()); } - else if (host_info.addresses ().size ()) + else { - auto server = host_info.addresses ()[0]; - if (blocked_addresses_.end () == std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server)) + auto const& server_addresses = host_info.addresses (); + if (server_addresses.size ()) { - server_ = server; - TRACE_UDP ("resulting server:" << server); + server_ = server_addresses[0]; + } + } + start (); +} - // send initial heartbeat which allows schema negotiation - heartbeat (); +void MessageClient::impl::start () +{ + if (server_.isNull ()) + { + Q_EMIT self_->close (); + pending_messages_.clear (); // discard + return; + } - // clear any backlog - while (pending_messages_.size ()) + if (blocked_addresses_.end () != std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server_)) + { + Q_EMIT self_->error ("UDP server blocked, please try another"); + pending_messages_.clear (); // discard + return; + } + + TRACE_UDP ("Trying server:" << server_.toString () << "on interface:" << network_interface_.humanReadableName ()); + QHostAddress interface_ip {QHostAddress::Any}; + if (network_interface_.isValid ()) + { + if (is_multicast_address (server_) && !(network_interface_.flags () & QNetworkInterface::CanMulticast)) + { + Q_EMIT self_->error ("Network interface is not multicast capable, please try another"); + return; + } + for (auto const& ae : network_interface_.addressEntries ()) + { + auto const& ip = ae.ip (); + if (server_.protocol () == ip.protocol ()) { - send_message (pending_messages_.dequeue ()); + interface_ip = ip; + break; } } - else + if (QHostAddress {QHostAddress::Any} == interface_ip) { - Q_EMIT self_->error ("UDP server blocked, please try another"); + Q_EMIT self_->error ("Network interface has no suitable address for server IP protocol, please try another"); pending_messages_.clear (); // discard + return; } } + + if (server_.isBroadcast ()) + { + // only allow broadcast on the loopback interface to avoid + // flooding the local subnet which may be large with some ISPs + //interface_ip.setAddress ("127.0.0.1"); + } + + if (localAddress () != interface_ip) + { + if (UnconnectedState != state () || state ()) + { + close (); + } + // bind to an ephemeral port on the selected interface and set + // up for sending datagrams + bind (interface_ip); + setMulticastInterface (network_interface_); + + // set multicast TTL to limit scope when sending to multicast + // group addresses + setSocketOption (MulticastTtlOption, TTL_); + } + + // send initial heartbeat which allows schema negotiation + heartbeat (); + + // clear any backlog + while (pending_messages_.size ()) + { + send_message (pending_messages_.dequeue ()); + } } void MessageClient::impl::pending_datagrams () @@ -428,9 +508,11 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre } MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision, - QString const& server, port_type server_port, QObject * self) + QString const& server_name, port_type server_port, + QString const& network_interface_name, + int TTL, QObject * self) : QObject {self} - , m_ {id, version, revision, server_port, this} + , m_ {id, version, revision, server_port, TTL, this} { connect (&*m_ #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) @@ -449,8 +531,8 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString #endif Q_EMIT error (m_->errorString ()); } - }); - set_server (server); + }); + m_->set_server (server_name, network_interface_name); } QHostAddress MessageClient::server_address () const @@ -463,20 +545,9 @@ auto MessageClient::server_port () const -> port_type return m_->server_port_; } -void MessageClient::set_server (QString const& server) +void MessageClient::set_server (QString const& server_name, QString const& network_interface_name) { - m_->server_.clear (); - m_->server_string_ = server; - if (server.size ()) - { - // queue a host address lookup - TRACE_UDP ("server host DNS lookup:" << server); -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) - m_->dns_lookup_id_ = QHostInfo::lookupHost (server, &*m_, &MessageClient::impl::host_info_results); -#else - m_->dns_lookup_id_ = QHostInfo::lookupHost (server, &*m_, SLOT (host_info_results (QHostInfo))); -#endif - } + m_->set_server (server_name, network_interface_name); } void MessageClient::set_server_port (port_type server_port) @@ -484,6 +555,12 @@ void MessageClient::set_server_port (port_type server_port) m_->server_port_ = server_port; } +void MessageClient::set_TTL (int TTL) +{ + m_->TTL_ = TTL; + m_->setSocketOption (QAbstractSocket::MulticastTtlOption, m_->TTL_); +} + void MessageClient::enable (bool flag) { m_->enabled_ = flag; @@ -499,7 +576,7 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Status, m_->id_, m_->schema_}; @@ -516,7 +593,7 @@ void MessageClient::decode (bool is_new, QTime time, qint32 snr, float delta_tim , QString const& mode, QString const& message_text, bool low_confidence , bool off_air) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Decode, m_->id_, m_->schema_}; @@ -531,7 +608,7 @@ void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delt , qint32 drift, QString const& callsign, QString const& grid, qint32 power , bool off_air) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::WSPRDecode, m_->id_, m_->schema_}; @@ -544,7 +621,7 @@ void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delt void MessageClient::decodes_cleared () { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Clear, m_->id_, m_->schema_}; @@ -561,7 +638,7 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr , QString const& my_grid, QString const& exchange_sent , QString const& exchange_rcvd, QString const& propmode) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_, m_->schema_}; @@ -576,7 +653,7 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr void MessageClient::logged_ADIF (QByteArray const& ADIF_record) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::LoggedADIF, m_->id_, m_->schema_}; diff --git a/Network/MessageClient.hpp b/Network/MessageClient.hpp index afe361fab..d0066dbe4 100644 --- a/Network/MessageClient.hpp +++ b/Network/MessageClient.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "Radio.hpp" #include "pimpl_h.hpp" @@ -34,19 +35,25 @@ public: // // messages will be silently dropped until a server host lookup is complete MessageClient (QString const& id, QString const& version, QString const& revision, - QString const& server, port_type server_port, QObject * parent = nullptr); + QString const& server_name, port_type server_port, + QString const& network_interface_name, + int TTL, QObject * parent = nullptr); // query server details QHostAddress server_address () const; port_type server_port () const; - // initiate a new server host lookup or is the server name is empty - // the sending of messages is disabled - Q_SLOT void set_server (QString const& server = QString {}); + // initiate a new server host lookup or if the server name is empty + // the sending of messages is disabled, if an interface is specified + // then that interface is used for outgoing datagrams + Q_SLOT void set_server (QString const& server_name, QString const& network_interface_name); // change the server port messages are sent to Q_SLOT void set_server_port (port_type server_port = 0u); + // change the server port messages are sent to + Q_SLOT void set_TTL (int TTL); + // enable incoming messages Q_SLOT void enable (bool); diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 42a9689ef..fc36aad9d 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -32,7 +32,6 @@ public: : self_ {self} , version_ {version} , revision_ {revision} - , port_ {0u} , clock_ {new QTimer {this}} { // register the required types with Qt @@ -78,8 +77,8 @@ public: MessageServer * self_; QString version_; QString revision_; - port_type port_; QHostAddress multicast_group_address_; + QStringList network_interfaces_; static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint; struct Client { @@ -109,56 +108,39 @@ MessageServer::impl::BindMode constexpr MessageServer::impl::bind_mode_; void MessageServer::impl::leave_multicast_group () { - if (!multicast_group_address_.isNull () && BoundState == state () -#if QT_VERSION >= 0x050600 - && multicast_group_address_.isMulticast () -#endif - ) + if (BoundState == state () && is_multicast_address (multicast_group_address_)) { - for (auto const& interface : QNetworkInterface::allInterfaces ()) + for (auto const& if_name : network_interfaces_) { - if (QNetworkInterface::CanMulticast & interface.flags ()) - { - leaveMulticastGroup (multicast_group_address_, interface); - } + leaveMulticastGroup (multicast_group_address_, QNetworkInterface::interfaceFromName (if_name)); } } } void MessageServer::impl::join_multicast_group () { - if (BoundState == state () - && !multicast_group_address_.isNull () -#if QT_VERSION >= 0x050600 - && multicast_group_address_.isMulticast () -#endif - ) + if (BoundState == state () && is_multicast_address (multicast_group_address_)) { - auto mcast_iface = multicastInterface (); - if (IPv4Protocol == multicast_group_address_.protocol () - && IPv4Protocol != localAddress ().protocol ()) + if (network_interfaces_.size ()) { - close (); - bind (QHostAddress::AnyIPv4, port_, bind_mode_); - } - bool joined {false}; - for (auto const& interface : QNetworkInterface::allInterfaces ()) - { - if (QNetworkInterface::CanMulticast & interface.flags ()) + for (auto const& if_name : network_interfaces_) { - // Windows requires outgoing interface to match - // interface to be joined while joining, at least for - // IPv4 it seems to - setMulticastInterface (interface); - - joined |= joinMulticastGroup (multicast_group_address_, interface); + joinMulticastGroup (multicast_group_address_, QNetworkInterface::interfaceFromName (if_name)); } } - if (!joined) + else { - multicast_group_address_.clear (); + // find the loop-back interface and join on that + for (auto const& net_if : QNetworkInterface::allInterfaces ()) + { + auto flags = QNetworkInterface::IsUp | QNetworkInterface::IsLoopBack | QNetworkInterface::CanMulticast; + if ((net_if.flags () & flags) == flags) + { + joinMulticastGroup (multicast_group_address_, net_if); + break; + } + } } - setMulticastInterface (mcast_iface); } } @@ -448,27 +430,34 @@ MessageServer::MessageServer (QObject * parent, QString const& version, QString { } -void MessageServer::start (port_type port, QHostAddress const& multicast_group_address) +void MessageServer::start (port_type port, QHostAddress const& multicast_group_address + , QStringList const& network_interface_names) { - if (port != m_->port_ - || multicast_group_address != m_->multicast_group_address_) + if (port != m_->localPort () || multicast_group_address != m_->multicast_group_address_) { m_->leave_multicast_group (); - if (impl::BoundState == m_->state ()) + if (impl::UnconnectedState != m_->state ()) { m_->close (); } - m_->multicast_group_address_ = multicast_group_address; - auto address = m_->multicast_group_address_.isNull () - || impl::IPv4Protocol != m_->multicast_group_address_.protocol () ? QHostAddress::Any : QHostAddress::AnyIPv4; - if (port && m_->bind (address, port, m_->bind_mode_)) + if (!(multicast_group_address.isNull () || is_multicast_address (multicast_group_address))) { - m_->port_ = port; - m_->join_multicast_group (); + Q_EMIT error ("Invalid multicast group address"); + } + else if (is_MAC_ambiguous_multicast_address (multicast_group_address)) + { + Q_EMIT error ("MAC-ambiguous IPv4 multicast group address not supported"); } else { - m_->port_ = 0; + m_->multicast_group_address_ = multicast_group_address; + m_->network_interfaces_ = network_interface_names; + QHostAddress local_addr {is_multicast_address (multicast_group_address) + && impl::IPv4Protocol == multicast_group_address.protocol () ? QHostAddress::AnyIPv4 : QHostAddress::Any}; + if (port && m_->bind (local_addr, port, m_->bind_mode_)) + { + m_->join_multicast_group (); + } } } } diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 184410117..449c70f4b 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -2,6 +2,8 @@ #define MESSAGE_SERVER_HPP__ #include +#include +#include #include #include #include @@ -38,8 +40,9 @@ public: // start or restart the server, if the multicast_group_address // argument is given it is assumed to be a multicast group address // which the server will join - Q_SLOT void start (port_type port, - QHostAddress const& multicast_group_address = QHostAddress {}); + Q_SLOT void start (port_type port + , QHostAddress const& multicast_group_address = QHostAddress {} + , QStringList const& network_interface_names = QStringList {}); // ask the client to clear one or both of the decode windows Q_SLOT void clear_decodes (QString const& id, quint8 window = 0); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index be1b5edeb..2668a6021 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -20,6 +20,9 @@ #include #include +#include +#include +#include #include #include #include @@ -144,7 +147,7 @@ class Server Q_OBJECT public: - Server (port_type port, QHostAddress const& multicast_group) + Server (port_type port, QHostAddress const& multicast_group, QStringList const& network_interface_names) : server_ {new MessageServer {this}} { // connect up server @@ -154,7 +157,7 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); - server_->start (port, multicast_group); + server_->start (port, multicast_group, network_interface_names); } private: @@ -232,9 +235,19 @@ int main (int argc, char * argv[]) app.translate ("UDPDaemon", "GROUP")); parser.addOption (multicast_addr_option); + QCommandLineOption network_interface_option (QStringList {"i", "network-interface"}, + app.translate ("UDPDaemon", + "Where is the network interface name to join on.\n" + "This option can be passed more than once to specify multiple network interfaces\n" + "The default is use just the loop back interface."), + app.translate ("UDPDaemon", "INTERFACE")); + parser.addOption (network_interface_option); + parser.process (app); - Server server {static_cast (parser.value (port_option).toUInt ()), QHostAddress {parser.value (multicast_addr_option)}}; + Server server {static_cast (parser.value (port_option).toUInt ()) + , QHostAddress {parser.value (multicast_addr_option).trimmed ()} + , parser.values (network_interface_option)}; return app.exec (); } diff --git a/qt_helpers.hpp b/qt_helpers.hpp index aae8c5f07..7170bda0b 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -117,6 +117,32 @@ namespace std } #endif + +inline +bool is_multicast_address (QHostAddress const& host_addr) +{ +#if QT_VERSION >= 0x050600 + return host_addr.isMulticast (); +#else + bool ok; + return (((host_addr.toIPv4Address (&ok) & 0xf0000000u) == 0xe0000000u) && ok) + || host_addr.toIPv6Address ()[0] == 0xff; +#endif +} + +inline +bool is_MAC_ambiguous_multicast_address (QHostAddress const& host_addr) +{ + // sub-ranges 224.128.0.0/24, 225.0.0.0/24, 225.128.0.0/24, + // 226.0.0.0/24, 226.128.0.0/24, ..., 239.0.0.0/24, 239.128.0.0/24 + // are not supported as they are inefficient due to ambiguous + // mappings to Ethernet MAC addresses. 224.0.0.0/24 alone is allowed + // from these ranges + bool ok; + auto ipv4 = host_addr.toIPv4Address (&ok); + return ok && !((ipv4 & 0xffffff00u) == 0xe0000000) && (ipv4 & 0xf07fff00) == 0xe0000000; +} + // Register some useful Qt types with QMetaType Q_DECLARE_METATYPE (QHostAddress); diff --git a/tests/test_qt_helpers.cpp b/tests/test_qt_helpers.cpp index cb6744df2..195c16e0d 100644 --- a/tests/test_qt_helpers.cpp +++ b/tests/test_qt_helpers.cpp @@ -131,6 +131,80 @@ private: QDateTime dt {QDate {2020, 8, 6}, QTime {14, 15, 22, 501}}; QCOMPARE (qt_truncate_date_time_to (dt, 7500), QDateTime (QDate (2020, 8, 6), QTime (14, 15, 22, 500))); } + + Q_SLOT void is_multicast_address_data () + { + QTest::addColumn ("addr"); + QTest::addColumn ("result"); + + QTest::newRow ("loopback") << "127.0.0.1" << false; + QTest::newRow ("looback IPv6") << "::1" << false; + QTest::newRow ("lowest-") << "223.255.255.255" << false; + QTest::newRow ("lowest") << "224.0.0.0" << true; + QTest::newRow ("lowest- IPv6") << "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << false; + QTest::newRow ("lowest IPv6") << "ff00::" << true; + QTest::newRow ("highest") << "239.255.255.255" << true; + QTest::newRow ("highest+") << "240.0.0.0" << false; + QTest::newRow ("highest IPv6") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << true; + } + + Q_SLOT void is_multicast_address () + { + QFETCH (QString, addr); + QFETCH (bool, result); + + QCOMPARE (::is_multicast_address (QHostAddress {addr}), result); + } + + Q_SLOT void is_MAC_ambiguous_multicast_address_data () + { + QTest::addColumn ("addr"); + QTest::addColumn ("result"); + + QTest::newRow ("loopback") << "127.0.0.1" << false; + QTest::newRow ("looback IPv6") << "::1" << false; + + QTest::newRow ("lowest- R1") << "223.255.255.255" << false; + QTest::newRow ("lowest R1") << "224.0.0.0" << false; + QTest::newRow ("highest R1") << "224.0.0.255" << false; + QTest::newRow ("highest+ R1") << "224.0.1.0" << false; + QTest::newRow ("lowest- R1A") << "224.127.255.255" << false; + QTest::newRow ("lowest R1A") << "224.128.0.0" << true; + QTest::newRow ("highest R1A") << "224.128.0.255" << true; + QTest::newRow ("highest+ R1A") << "224.128.1.0" << false; + + QTest::newRow ("lowest- R2") << "224.255.255.255" << false; + QTest::newRow ("lowest R2") << "225.0.0.0" << true; + QTest::newRow ("highest R2") << "225.0.0.255" << true; + QTest::newRow ("highest+ R2") << "225.0.1.0" << false; + QTest::newRow ("lowest- R2A") << "225.127.255.255" << false; + QTest::newRow ("lowest R2A") << "225.128.0.0" << true; + QTest::newRow ("highest R2A") << "225.128.0.255" << true; + QTest::newRow ("highest+ R2A") << "225.128.1.0" << false; + + QTest::newRow ("lowest- R3") << "238.255.255.255" << false; + QTest::newRow ("lowest R3") << "239.0.0.0" << true; + QTest::newRow ("highest R3") << "239.0.0.255" << true; + QTest::newRow ("highest+ R3") << "239.0.1.0" << false; + QTest::newRow ("lowest- R3A") << "239.127.255.255" << false; + QTest::newRow ("lowest R3A") << "239.128.0.0" << true; + QTest::newRow ("highest R3A") << "239.128.0.255" << true; + QTest::newRow ("highest+ R3A") << "239.128.1.0" << false; + + QTest::newRow ("lowest- IPv6") << "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << false; + QTest::newRow ("lowest IPv6") << "ff00::" << false; + QTest::newRow ("highest") << "239.255.255.255" << false; + QTest::newRow ("highest+") << "240.0.0.0" << false; + QTest::newRow ("highest IPv6") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << false; + } + + Q_SLOT void is_MAC_ambiguous_multicast_address () + { + QFETCH (QString, addr); + QFETCH (bool, result); + + QCOMPARE (::is_MAC_ambiguous_multicast_address (QHostAddress {addr}), result); + } }; QTEST_MAIN (TestQtHelpers); diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index d20331bc4..6fb8e1a5a 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -414,6 +414,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_messageClient {new MessageClient {QApplication::applicationName (), version (), revision (), m_config.udp_server_name (), m_config.udp_server_port (), + m_config.udp_interface_name (), m_config.udp_TTL (), this}}, m_psk_Reporter {&m_config, QString {"WSJT-X v" + version () + " " + m_revision}.simplified ()}, m_manual {&m_network_manager}, @@ -782,6 +783,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, connect (&m_config, &Configuration::transceiver_failure, this, &MainWindow::handle_transceiver_failure); connect (&m_config, &Configuration::udp_server_changed, m_messageClient, &MessageClient::set_server); connect (&m_config, &Configuration::udp_server_port_changed, m_messageClient, &MessageClient::set_server_port); + connect (&m_config, &Configuration::udp_TTL_changed, m_messageClient, &MessageClient::set_TTL); connect (&m_config, &Configuration::accept_udp_requests_changed, m_messageClient, &MessageClient::enable); connect (&m_config, &Configuration::enumerating_audio_devices, [this] () { showStatusMessage (tr ("Enumerating audio devices")); @@ -7824,7 +7826,7 @@ void MainWindow::networkError (QString const& e) , MessageBox::Cancel)) { // retry server lookup - m_messageClient->set_server (m_config.udp_server_name ()); + m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_name ()); } } From 93d1e17005310b2b2719ad142ea0d9bcab1e5444 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 2 Nov 2020 21:35:48 +0000 Subject: [PATCH 30/73] Extend UDP MessageServer client mapping key with the host address The UDP Example reference applications now work correctly with WSJT-X instances with duplicate --rig-name= command line arguments so long as duplicate instances are run on unique hosts. --- UDPExamples/BeaconsModel.cpp | 19 +-- UDPExamples/BeaconsModel.hpp | 6 +- UDPExamples/ClientWidget.cpp | 78 ++++++------- UDPExamples/ClientWidget.hpp | 34 +++--- UDPExamples/DecodesModel.cpp | 26 +++-- UDPExamples/DecodesModel.hpp | 10 +- UDPExamples/MessageAggregatorMainWindow.cpp | 28 +++-- UDPExamples/MessageAggregatorMainWindow.hpp | 10 +- UDPExamples/MessageServer.cpp | 122 ++++++++++---------- UDPExamples/MessageServer.hpp | 63 +++++----- UDPExamples/UDPDaemon.cpp | 72 +++++++----- 11 files changed, 251 insertions(+), 217 deletions(-) diff --git a/UDPExamples/BeaconsModel.cpp b/UDPExamples/BeaconsModel.cpp index 7ac1323a1..8a6cdd279 100644 --- a/UDPExamples/BeaconsModel.cpp +++ b/UDPExamples/BeaconsModel.cpp @@ -25,10 +25,13 @@ namespace QFont text_font {"Courier", 10}; - QList make_row (QString const& client_id, QTime time, qint32 snr, float delta_time + QList make_row (MessageServer::ClientKey const& key, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { + auto client_item = new QStandardItem {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; + client_item->setData (QVariant::fromValue (key)); + auto time_item = new QStandardItem {time.toString ("hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -60,7 +63,7 @@ namespace live->setTextAlignment (Qt::AlignHCenter); QList row { - new QStandardItem {client_id}, time_item, snr_item, dt, freq, dri, gd, pwr, live, new QStandardItem {callsign}}; + client_item, time_item, snr_item, dt, freq, dri, gd, pwr, live, new QStandardItem {callsign}}; Q_FOREACH (auto& item, row) { item->setEditable (false); @@ -81,7 +84,7 @@ BeaconsModel::BeaconsModel (QObject * parent) } } -void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time +void BeaconsModel::add_beacon_spot (bool is_new, ClientKey const& key, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { @@ -90,7 +93,7 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime int target_row {-1}; for (auto row = 0; row < rowCount (); ++row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { auto row_time = item (row, 1)->data ().toTime (); if (row_time == time @@ -113,19 +116,19 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); + insertRow (target_row + 1, make_row (key, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); + appendRow (make_row (key, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); } -void BeaconsModel::decodes_cleared (QString const& client_id) +void BeaconsModel::decodes_cleared (ClientKey const& key) { for (auto row = rowCount () - 1; row >= 0; --row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { removeRow (row); } diff --git a/UDPExamples/BeaconsModel.hpp b/UDPExamples/BeaconsModel.hpp index b089349cc..2baa99ec3 100644 --- a/UDPExamples/BeaconsModel.hpp +++ b/UDPExamples/BeaconsModel.hpp @@ -26,13 +26,15 @@ class BeaconsModel { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit BeaconsModel (QObject * parent = nullptr); - Q_SLOT void add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time + Q_SLOT void add_beacon_spot (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign, QString const& grid , qint32 power, bool off_air); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const&); }; #endif diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index b2ee03609..3be8c788c 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -27,9 +27,9 @@ namespace } } -ClientWidget::IdFilterModel::IdFilterModel (QString const& client_id, QObject * parent) +ClientWidget::IdFilterModel::IdFilterModel (ClientKey const& key, QObject * parent) : QSortFilterProxyModel {parent} - , client_id_ {client_id} + , key_ {key} , rx_df_ (quint32_max) { } @@ -73,7 +73,7 @@ bool ClientWidget::IdFilterModel::filterAcceptsRow (int source_row , QModelIndex const& source_parent) const { auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent); - return sourceModel ()->data (source_index_col0).toString () == client_id_; + return sourceModel ()->data (source_index_col0).value () == key_; } void ClientWidget::IdFilterModel::de_call (QString const& call) @@ -106,9 +106,9 @@ void ClientWidget::IdFilterModel::rx_df (quint32 df) namespace { - QString make_title (QString const& id, QString const& version, QString const& revision) + QString make_title (MessageServer::ClientKey const& key, QString const& version, QString const& revision) { - QString title {id}; + QString title {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; if (version.size ()) { title += QString {" v%1"}.arg (version); @@ -122,14 +122,14 @@ namespace } ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model - , QString const& id, QString const& version, QString const& revision + , ClientKey const& key, QString const& version, QString const& revision , QListWidget const * calls_of_interest, QWidget * parent) - : QDockWidget {make_title (id, version, revision), parent} - , id_ {id} + : QDockWidget {make_title (key, version, revision), parent} + , key_ {key} , done_ {false} , calls_of_interest_ {calls_of_interest} - , decodes_proxy_model_ {id} - , beacons_proxy_model_ {id} + , decodes_proxy_model_ {key} + , beacons_proxy_model_ {key} , erase_action_ {new QAction {tr ("&Erase Band Activity"), this}} , erase_rx_frequency_action_ {new QAction {tr ("Erase &Rx Frequency"), this}} , erase_both_action_ {new QAction {tr ("Erase &Both"), this}} @@ -209,56 +209,56 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod horizontal_layout_->addLayout (subform3_layout_); connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) { - Q_EMIT do_free_text (id_, text, false); + Q_EMIT do_free_text (key_, text, false); }); connect (message_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT do_free_text (id_, message_line_edit_->text (), true); + Q_EMIT do_free_text (key_, message_line_edit_->text (), true); }); connect (grid_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT location (id_, grid_line_edit_->text ()); + Q_EMIT location (key_, grid_line_edit_->text ()); }); connect (configuration_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT switch_configuration (id_, configuration_line_edit_->text ()); + Q_EMIT switch_configuration (key_, configuration_line_edit_->text ()); }); connect (mode_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, mode_line_edit_->text (), quint32_max, empty, fast_mode () + Q_EMIT configure (key_, mode_line_edit_->text (), quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (frequency_tolerance_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; auto f = frequency_tolerance_spin_box_->specialValueText ().size () ? quint32_max : i; - Q_EMIT configure (id_, empty, f, empty, fast_mode () + Q_EMIT configure (key_, empty, f, empty, fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (submode_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, submode_line_edit_->text (), fast_mode () + Q_EMIT configure (key_, empty, quint32_max, submode_line_edit_->text (), fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (fast_mode_check_box_, &QCheckBox::stateChanged, [this] (int state) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, Qt::Checked == state + Q_EMIT configure (key_, empty, quint32_max, empty, Qt::Checked == state , quint32_max, quint32_max, empty, empty, false); }); connect (tr_period_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , i, quint32_max, empty, empty, false); }); connect (rx_df_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, i, empty, empty, false); }); connect (dx_call_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, dx_call_line_edit_->text (), empty, false); }); connect (dx_grid_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, dx_grid_line_edit_->text (), false); }); @@ -289,14 +289,14 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod halt_tx_button_ = control_button_box_->addButton (tr ("&Halt Tx"), QDialogButtonBox::ActionRole); connect (generate_messages_push_button_, &QAbstractButton::clicked, [this] (bool /*checked*/) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, empty, true); }); connect (auto_off_button_, &QAbstractButton::clicked, [this] (bool /* checked */) { - Q_EMIT do_halt_tx (id_, true); + Q_EMIT do_halt_tx (key_, true); }); connect (halt_tx_button_, &QAbstractButton::clicked, [this] (bool /* checked */) { - Q_EMIT do_halt_tx (id_, false); + Q_EMIT do_halt_tx (key_, false); }); content_layout_->addWidget (control_button_box_); @@ -318,13 +318,13 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // connect context menu actions connect (erase_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_); + Q_EMIT do_clear_decodes (key_); }); connect (erase_rx_frequency_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_, 1); + Q_EMIT do_clear_decodes (key_, 1); }); connect (erase_both_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_, 2); + Q_EMIT do_clear_decodes (key_, 2); }); // connect up table view signals @@ -335,7 +335,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // tell new client about calls of interest for (int row = 0; row < calls_of_interest_->count (); ++row) { - Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow}); + Q_EMIT highlight_callsign (key_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow}); } } @@ -349,7 +349,7 @@ void ClientWidget::closeEvent (QCloseEvent *e) { if (!done_) { - Q_EMIT do_close (id_); + Q_EMIT do_close (key_); e->ignore (); // defer closure until client actually closes } else @@ -363,7 +363,7 @@ ClientWidget::~ClientWidget () for (int row = 0; row < calls_of_interest_->count (); ++row) { // tell client to forget calls of interest - Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text ()); + Q_EMIT highlight_callsign (key_, calls_of_interest_->item (row)->text ()); } } @@ -395,7 +395,7 @@ namespace } } -void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call +void ClientWidget::update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid @@ -403,7 +403,7 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name) { - if (id == id_) + if (key == key_) { fast_mode_check_box_->setChecked (fast_mode); decodes_proxy_model_.de_call (de_call); @@ -447,11 +447,11 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& } } -void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ +void ClientWidget::decode_added (bool /*is_new*/, ClientKey const& key, QTime /*time*/, qint32 /*snr*/ , float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/ , QString const& /*message*/, bool /*low_confidence*/, bool /*off_air*/) { - if (client_id == id_ && !columns_resized_) + if (key == key_ && !columns_resized_) { decodes_stack_->setCurrentIndex (0); decodes_table_view_->resizeColumnsToContents (); @@ -460,12 +460,12 @@ void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTim decodes_table_view_->scrollToBottom (); } -void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ +void ClientWidget::beacon_spot_added (bool /*is_new*/, ClientKey const& key, QTime /*time*/, qint32 /*snr*/ , float /*delta_time*/, Frequency /*delta_frequency*/, qint32 /*drift*/ , QString const& /*callsign*/, QString const& /*grid*/, qint32 /*power*/ , bool /*off_air*/) { - if (client_id == id_ && !columns_resized_) + if (key == key_ && !columns_resized_) { decodes_stack_->setCurrentIndex (1); beacons_table_view_->resizeColumnsToContents (); @@ -474,9 +474,9 @@ void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, beacons_table_view_->scrollToBottom (); } -void ClientWidget::decodes_cleared (QString const& client_id) +void ClientWidget::decodes_cleared (ClientKey const& key) { - if (client_id == id_) + if (key == key_) { columns_resized_ = false; } diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index 983ddd874..ee91d084a 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -35,42 +35,44 @@ class ClientWidget { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model - , QString const& id, QString const& version, QString const& revision + , ClientKey const& key, QString const& version, QString const& revision , QListWidget const * calls_of_interest, QWidget * parent = nullptr); void dispose (); ~ClientWidget (); bool fast_mode () const; - Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call + Q_SLOT void update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name); - Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr + Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); - Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime, qint32 snr + Q_SLOT void beacon_spot_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, Frequency delta_frequency, qint32 drift , QString const& callsign, QString const& grid, qint32 power , bool off_air); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const& key); - Q_SIGNAL void do_clear_decodes (QString const& id, quint8 window = 0); - Q_SIGNAL void do_close (QString const& id); + Q_SIGNAL void do_clear_decodes (ClientKey const& key, quint8 window = 0); + Q_SIGNAL void do_close (ClientKey const& key); Q_SIGNAL void do_reply (QModelIndex const&, quint8 modifier); - Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only); - Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool); - Q_SIGNAL void location (QString const& id, QString const& text); - Q_SIGNAL void highlight_callsign (QString const& id, QString const& call + Q_SIGNAL void do_halt_tx (ClientKey const& key, bool auto_only); + Q_SIGNAL void do_free_text (ClientKey const& key, QString const& text, bool); + Q_SIGNAL void location (ClientKey const& key, QString const& text); + Q_SIGNAL void highlight_callsign (ClientKey const& key, QString const& call , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); - Q_SIGNAL void switch_configuration (QString const& id, QString const& configuration_name); - Q_SIGNAL void configure (QString const& id, QString const& mode, quint32 frequency_tolerance + Q_SIGNAL void switch_configuration (ClientKey const& key, QString const& configuration_name); + Q_SIGNAL void configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages); @@ -79,7 +81,7 @@ private: : public QSortFilterProxyModel { public: - IdFilterModel (QString const& client_id, QObject * = nullptr); + IdFilterModel (ClientKey const& key, QObject * = nullptr); void de_call (QString const&); void rx_df (quint32); @@ -88,7 +90,7 @@ private: private: bool filterAcceptsRow (int source_row, QModelIndex const& source_parent) const override; - QString client_id_; + ClientKey key_; QString call_; QRegularExpression base_call_re_; quint32 rx_df_; @@ -96,7 +98,7 @@ private: void closeEvent (QCloseEvent *) override; - QString id_; + ClientKey key_; bool done_; QListWidget const * calls_of_interest_; IdFilterModel decodes_proxy_model_; diff --git a/UDPExamples/DecodesModel.cpp b/UDPExamples/DecodesModel.cpp index 6121ff31a..7b8d87c52 100644 --- a/UDPExamples/DecodesModel.cpp +++ b/UDPExamples/DecodesModel.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -33,10 +34,13 @@ namespace QFont text_font {"Courier", 10}; - QList make_row (QString const& client_id, QTime time, qint32 snr, float delta_time - , quint32 delta_frequency, QString const& mode, QString const& message - , bool low_confidence, bool off_air, bool is_fast) + QList make_row (MessageServer::ClientKey const& key, QTime time, qint32 snr + , float delta_time, quint32 delta_frequency, QString const& mode + , QString const& message, bool low_confidence, bool off_air, bool is_fast) { + auto client_item = new QStandardItem {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; + client_item->setData (QVariant::fromValue (key)); + auto time_item = new QStandardItem {time.toString (is_fast || "~" == mode ? "hh:mm:ss" : "hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -63,7 +67,7 @@ namespace live->setTextAlignment (Qt::AlignHCenter); QList row { - new QStandardItem {client_id}, time_item, snr_item, dt, df, md, confidence, live, new QStandardItem {message}}; + client_item, time_item, snr_item, dt, df, md, confidence, live, new QStandardItem {message}}; Q_FOREACH (auto& item, row) { item->setEditable (false); @@ -84,7 +88,7 @@ DecodesModel::DecodesModel (QObject * parent) } } -void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time +void DecodesModel::add_decode (bool is_new, ClientKey const& key, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air, bool is_fast) { @@ -93,7 +97,7 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time int target_row {-1}; for (auto row = 0; row < rowCount (); ++row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { auto row_time = item (row, 1)->data ().toTime (); if (row_time == time @@ -115,21 +119,21 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode + insertRow (target_row + 1, make_row (key, time, snr, delta_time, delta_frequency, mode , message, low_confidence, off_air, is_fast)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message, low_confidence + appendRow (make_row (key, time, snr, delta_time, delta_frequency, mode, message, low_confidence , off_air, is_fast)); } -void DecodesModel::decodes_cleared (QString const& client_id) +void DecodesModel::decodes_cleared (ClientKey const& key) { for (auto row = rowCount () - 1; row >= 0; --row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { removeRow (row); } @@ -139,7 +143,7 @@ void DecodesModel::decodes_cleared (QString const& client_id) void DecodesModel::do_reply (QModelIndex const& source, quint8 modifiers) { auto row = source.row (); - Q_EMIT reply (data (index (row, 0)).toString () + Q_EMIT reply (item (row, 0)->data ().value () , item (row, 1)->data ().toTime () , item (row, 2)->data ().toInt () , item (row, 3)->data ().toFloat () diff --git a/UDPExamples/DecodesModel.hpp b/UDPExamples/DecodesModel.hpp index 17c9ae125..27a168c87 100644 --- a/UDPExamples/DecodesModel.hpp +++ b/UDPExamples/DecodesModel.hpp @@ -5,8 +5,6 @@ #include "MessageServer.hpp" -using Frequency = MessageServer::Frequency; - class QTime; class QString; class QModelIndex; @@ -28,16 +26,18 @@ class DecodesModel { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit DecodesModel (QObject * parent = nullptr); - Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time + Q_SLOT void add_decode (bool is_new, ClientKey const&, QTime, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air, bool is_fast); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const&); Q_SLOT void do_reply (QModelIndex const& source, quint8 modifiers); - Q_SIGNAL void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency + Q_SIGNAL void reply (ClientKey const&, QTime, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence, quint8 modifiers); }; diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index ba034b0e2..7e74342c0 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -184,13 +184,16 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () connect (server_, &MessageServer::client_closed, this, &MessageAggregatorMainWindow::remove_client); connect (server_, &MessageServer::client_closed, decodes_model_, &DecodesModel::decodes_cleared); connect (server_, &MessageServer::client_closed, beacons_model_, &BeaconsModel::decodes_cleared); - connect (server_, &MessageServer::decode, [this] (bool is_new, QString const& id, QTime time + connect (server_, &MessageServer::decode, [this] (bool is_new, ClientKey const& key, QTime time , qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence , bool off_air) { - decodes_model_->add_decode (is_new, id, time, snr, delta_time, delta_frequency, mode, message - , low_confidence, off_air, dock_widgets_[id]->fast_mode ());}); + decodes_model_->add_decode (is_new, key, time, snr, delta_time + , delta_frequency, mode, message + , low_confidence, off_air + , dock_widgets_[key]->fast_mode ()); + }); connect (server_, &MessageServer::WSPR_decode, beacons_model_, &BeaconsModel::add_beacon_spot); connect (server_, &MessageServer::decodes_cleared, decodes_model_, &DecodesModel::decodes_cleared); connect (server_, &MessageServer::decodes_cleared, beacons_model_, &BeaconsModel::decodes_cleared); @@ -207,7 +210,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () show (); } -void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call +void MessageAggregatorMainWindow::log_qso (ClientKey const& /*key*/, QDateTime time_off + , QString const& dx_call , QString const& dx_grid, Frequency dial_frequency, QString const& mode , QString const& report_sent, QString const& report_received , QString const& tx_power, QString const& comments @@ -240,9 +244,9 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time log_table_view_->scrollToBottom (); } -void MessageAggregatorMainWindow::add_client (QString const& id, QString const& version, QString const& revision) +void MessageAggregatorMainWindow::add_client (ClientKey const& key, QString const& version, QString const& revision) { - auto dock = new ClientWidget {decodes_model_, beacons_model_, id, version, revision, calls_of_interest_, this}; + auto dock = new ClientWidget {decodes_model_, beacons_model_, key, version, revision, calls_of_interest_, this}; dock->setAttribute (Qt::WA_DeleteOnClose); auto view_action = dock->toggleViewAction (); view_action->setEnabled (true); @@ -262,13 +266,13 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const& connect (dock, &ClientWidget::highlight_callsign, server_, &MessageServer::highlight_callsign); connect (dock, &ClientWidget::switch_configuration, server_, &MessageServer::switch_configuration); connect (dock, &ClientWidget::configure, server_, &MessageServer::configure); - dock_widgets_[id] = dock; - server_->replay (id); // request decodes and status + dock_widgets_[key] = dock; + server_->replay (key); // request decodes and status } -void MessageAggregatorMainWindow::remove_client (QString const& id) +void MessageAggregatorMainWindow::remove_client (ClientKey const& key) { - auto iter = dock_widgets_.find (id); + auto iter = dock_widgets_.find (key); if (iter != std::end (dock_widgets_)) { (*iter)->dispose (); @@ -287,9 +291,9 @@ MessageAggregatorMainWindow::~MessageAggregatorMainWindow () void MessageAggregatorMainWindow::change_highlighting (QString const& call, QColor const& bg, QColor const& fg , bool last_only) { - for (auto id : dock_widgets_.keys ()) + for (auto key : dock_widgets_.keys ()) { - server_->highlight_callsign (id, call, bg, fg, last_only); + server_->highlight_callsign (key, call, bg, fg, last_only); } } diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 045f4e945..445a5908e 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -24,11 +24,13 @@ class MessageAggregatorMainWindow { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: MessageAggregatorMainWindow (); ~MessageAggregatorMainWindow (); - Q_SLOT void log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SLOT void log_qso (ClientKey const&, QDateTime time_off, QString const& dx_call, QString const& dx_grid , Frequency dial_frequency, QString const& mode, QString const& report_sent , QString const& report_received, QString const& tx_power, QString const& comments , QString const& name, QDateTime time_on, QString const& operator_call @@ -36,13 +38,13 @@ public: , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); private: - void add_client (QString const& id, QString const& version, QString const& revision); - void remove_client (QString const& id); + void add_client (ClientKey const&, QString const& version, QString const& revision); + void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, bool last_only = false); // maps client id to widgets - using ClientsDictionary = QHash; + using ClientsDictionary = QHash; ClientsDictionary dock_widgets_; QStandardItemModel * log_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index fc36aad9d..8869c4b89 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -83,9 +83,8 @@ public: struct Client { Client () = default; - Client (QHostAddress const& sender_address, port_type const& sender_port) - : sender_address_ {sender_address} - , sender_port_ {sender_port} + Client (port_type const& sender_port) + : sender_port_ {sender_port} , negotiated_schema_number_ {2} // not 1 because it's broken , last_activity_ {QDateTime::currentDateTime ()} { @@ -93,12 +92,11 @@ public: Client (Client const&) = default; Client& operator= (Client const&) = default; - QHostAddress sender_address_; port_type sender_port_; quint32 negotiated_schema_number_; QDateTime last_activity_; }; - QHash clients_; // maps id to Client + QHash clients_; // maps id to Client QTimer * clock_; }; @@ -171,9 +169,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s auto id = in.id (); if (OK == check_status (in)) { - if (!clients_.contains (id)) + auto client_key = ClientKey {sender, id}; + if (!clients_.contains (client_key)) { - auto& client = (clients_[id] = {sender, sender_port}); + auto& client = (clients_[client_key] = {sender_port}); QByteArray client_version; QByteArray client_revision; @@ -194,7 +193,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s << version_.toUtf8 () << revision_.toUtf8 (); if (impl::OK == check_status (hb)) { - writeDatagram (message, client.sender_address_, client.sender_port_); + writeDatagram (message, client_key.first, sender_port); } else { @@ -204,10 +203,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s // we don't care if this fails to read in >> client_version >> client_revision; } - Q_EMIT self_->client_opened (id, QString::fromUtf8 (client_version), + Q_EMIT self_->client_opened (client_key, QString::fromUtf8 (client_version), QString::fromUtf8 (client_revision)); } - clients_[id].last_activity_ = QDateTime::currentDateTime (); + clients_[client_key].last_activity_ = QDateTime::currentDateTime (); // // message format is described in NetworkMessage.hpp @@ -219,7 +218,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s break; case NetworkMessage::Clear: - Q_EMIT self_->decodes_cleared (id); + Q_EMIT self_->decodes_cleared (client_key); break; case NetworkMessage::Status: @@ -250,7 +249,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name; if (check_status (in) != Fail) { - Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) + Q_EMIT self_->status_update (client_key, f, QString::fromUtf8 (mode) + , QString::fromUtf8 (dx_call) , QString::fromUtf8 (report), QString::fromUtf8 (tx_mode) , tx_enabled, transmitting, decoding, rx_df, tx_df , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) @@ -278,7 +278,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> message >> low_confidence >> off_air; if (check_status (in) != Fail) { - Q_EMIT self_->decode (is_new, id, time, snr, delta_time, delta_frequency + Q_EMIT self_->decode (is_new, client_key, time, snr, delta_time, delta_frequency , QString::fromUtf8 (mode), QString::fromUtf8 (message) , low_confidence, off_air); } @@ -302,7 +302,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> off_air; if (check_status (in) != Fail) { - Q_EMIT self_->WSPR_decode (is_new, id, time, snr, delta_time, frequency, drift + Q_EMIT self_->WSPR_decode (is_new, client_key, time, snr, delta_time, frequency, drift , QString::fromUtf8 (callsign), QString::fromUtf8 (grid) , power, off_air); } @@ -333,8 +333,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> exchange_sent >> exchange_rcvd >> prop_mode; if (check_status (in) != Fail) { - Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid) - , dial_frequency, QString::fromUtf8 (mode), QString::fromUtf8 (report_sent) + Q_EMIT self_->qso_logged (client_key, time_off, QString::fromUtf8 (dx_call) + , QString::fromUtf8 (dx_grid) + , dial_frequency, QString::fromUtf8 (mode) + , QString::fromUtf8 (report_sent) , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power) , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call) @@ -345,8 +347,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s break; case NetworkMessage::Close: - Q_EMIT self_->client_closed (id); - clients_.remove (id); + Q_EMIT self_->client_closed (client_key); + clients_.remove (client_key); break; case NetworkMessage::LoggedADIF: @@ -355,7 +357,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s in >> ADIF; if (check_status (in) != Fail) { - Q_EMIT self_->logged_ADIF (id, ADIF); + Q_EMIT self_->logged_ADIF (client_key, ADIF); } } break; @@ -388,7 +390,7 @@ void MessageServer::impl::tick () { if (now > (*iter).last_activity_.addSecs (NetworkMessage::pulse)) { - Q_EMIT self_->clear_decodes (iter.key ()); + Q_EMIT self_->decodes_cleared (iter.key ()); Q_EMIT self_->client_closed (iter.key ()); iter = clients_.erase (iter); // safe while iterating as doesn't rehash } @@ -462,127 +464,127 @@ void MessageServer::start (port_type port, QHostAddress const& multicast_group_a } } -void MessageServer::clear_decodes (QString const& id, quint8 window) +void MessageServer::clear_decodes (ClientKey const& key, quint8 window) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Clear, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Clear, key.second, (*iter).negotiated_schema_number_}; out << window; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time +void MessageServer::reply (ClientKey const& key, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode , QString const& message_text, bool low_confidence, quint8 modifiers) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Reply, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Reply, key.second, (*iter).negotiated_schema_number_}; out << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 () << low_confidence << modifiers; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::replay (QString const& id) +void MessageServer::replay (ClientKey const& key) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Replay, id, (*iter).negotiated_schema_number_}; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + NetworkMessage::Builder out {&message, NetworkMessage::Replay, key.second, (*iter).negotiated_schema_number_}; + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::close (QString const& id) +void MessageServer::close (ClientKey const& key) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Close, id, (*iter).negotiated_schema_number_}; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + NetworkMessage::Builder out {&message, NetworkMessage::Close, key.second, (*iter).negotiated_schema_number_}; + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::halt_tx (QString const& id, bool auto_only) +void MessageServer::halt_tx (ClientKey const& key, bool auto_only) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, key.second, (*iter).negotiated_schema_number_}; out << auto_only; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::free_text (QString const& id, QString const& text, bool send) +void MessageServer::free_text (ClientKey const& key, QString const& text, bool send) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::FreeText, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::FreeText, key.second, (*iter).negotiated_schema_number_}; out << text.toUtf8 () << send; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::location (QString const& id, QString const& loc) +void MessageServer::location (ClientKey const& key, QString const& loc) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Location, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Location, key.second, (*iter).negotiated_schema_number_}; out << loc.toUtf8 (); - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::highlight_callsign (QString const& id, QString const& callsign +void MessageServer::highlight_callsign (ClientKey const& key, QString const& callsign , QColor const& bg, QColor const& fg, bool last_only) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, key.second, (*iter).negotiated_schema_number_}; out << callsign.toUtf8 () << bg << fg << last_only; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::switch_configuration (QString const& id, QString const& configuration_name) +void MessageServer::switch_configuration (ClientKey const& key, QString const& configuration_name) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, key.second, (*iter).negotiated_schema_number_}; out << configuration_name.toUtf8 (); - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::configure (QString const& id, QString const& mode, quint32 frequency_tolerance +void MessageServer::configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Configure, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Configure, key.second, (*iter).negotiated_schema_number_}; out << mode.toUtf8 () << frequency_tolerance << submode.toUtf8 () << fast_mode << tr_period << rx_df << dx_call.toUtf8 () << dx_grid.toUtf8 () << generate_messages; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 449c70f4b..8a31e7bd5 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -2,6 +2,7 @@ #define MESSAGE_SERVER_HPP__ #include +#include #include #include #include @@ -33,6 +34,7 @@ class UDP_EXPORT MessageServer public: using port_type = quint16; using Frequency = Radio::Frequency; + using ClientKey = QPair; MessageServer (QObject * parent = nullptr, QString const& version = QString {}, QString const& revision = QString {}); @@ -45,73 +47,72 @@ public: , QStringList const& network_interface_names = QStringList {}); // ask the client to clear one or both of the decode windows - Q_SLOT void clear_decodes (QString const& id, quint8 window = 0); + Q_SLOT void clear_decodes (ClientKey const&, quint8 window = 0); // ask the client with identification 'id' to make the same action // as a double click on the decode would // // note that the client is not obliged to take any action and only // takes any action if the decode is present and is a CQ or QRZ message - Q_SLOT void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency + Q_SLOT void reply (ClientKey const&, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence, quint8 modifiers); - // ask the client with identification 'id' to close down gracefully - Q_SLOT void close (QString const& id); + // ask the client to close down gracefully + Q_SLOT void close (ClientKey const&); - // ask the client with identification 'id' to replay all decodes - Q_SLOT void replay (QString const& id); + // ask the client to replay all decodes + Q_SLOT void replay (ClientKey const&); - // ask the client with identification 'id' to halt transmitting - // auto_only just disables auto Tx, otherwise halt is immediate - Q_SLOT void halt_tx (QString const& id, bool auto_only); + // ask the client to halt transmitting auto_only just disables auto + // Tx, otherwise halt is immediate + Q_SLOT void halt_tx (ClientKey const&, bool auto_only); - // ask the client with identification 'id' to set the free text - // message and optionally send it ASAP - Q_SLOT void free_text (QString const& id, QString const& text, bool send); + // ask the client to set the free text message and optionally send + // it ASAP + Q_SLOT void free_text (ClientKey const&, QString const& text, bool send); - // ask the client with identification 'id' to set the location provided - Q_SLOT void location (QString const& id, QString const& location); + // ask the client to set the location provided + Q_SLOT void location (ClientKey const&, QString const& location); - // ask the client with identification 'id' to highlight the callsign - // specified with the given colors - Q_SLOT void highlight_callsign (QString const& id, QString const& callsign + // ask the client to highlight the callsign specified with the given + // colors + Q_SLOT void highlight_callsign (ClientKey const&, QString const& callsign , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); - // ask the client with identification 'id' to switch to - // configuration 'configuration_name' - Q_SLOT void switch_configuration (QString const& id, QString const& configuration_name); + // ask the client to switch to configuration 'configuration_name' + Q_SLOT void switch_configuration (ClientKey const&, QString const& configuration_name); - // ask the client with identification 'id' to change configuration - Q_SLOT void configure (QString const& id, QString const& mode, quint32 frequency_tolerance + // ask the client to change configuration + Q_SLOT void configure (ClientKey const&, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages); // the following signals are emitted when a client broadcasts the // matching message - Q_SIGNAL void client_opened (QString const& id, QString const& version, QString const& revision); - Q_SIGNAL void status_update (QString const& id, Frequency, QString const& mode, QString const& dx_call + Q_SIGNAL void client_opened (ClientKey const&, QString const& version, QString const& revision); + Q_SIGNAL void status_update (ClientKey const&, Frequency, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name); - Q_SIGNAL void client_closed (QString const& id); - Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time + Q_SIGNAL void client_closed (ClientKey const&); + Q_SIGNAL void decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air); - Q_SIGNAL void WSPR_decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time, Frequency + Q_SIGNAL void WSPR_decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time, Frequency , qint32 drift, QString const& callsign, QString const& grid, qint32 power , bool off_air); - Q_SIGNAL void qso_logged (QString const& id, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SIGNAL void qso_logged (ClientKey const&, QDateTime time_off, QString const& dx_call, QString const& dx_grid , Frequency dial_frequency, QString const& mode, QString const& report_sent , QString const& report_received, QString const& tx_power, QString const& comments , QString const& name, QDateTime time_on, QString const& operator_call , QString const& my_call, QString const& my_grid , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); - Q_SIGNAL void decodes_cleared (QString const& id); - Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF); + Q_SIGNAL void decodes_cleared (ClientKey const&); + Q_SIGNAL void logged_ADIF (ClientKey const&, QByteArray const& ADIF); // this signal is emitted when a network error occurs Q_SIGNAL void error (QString const&) const; @@ -121,4 +122,6 @@ private: pimpl m_; }; +Q_DECLARE_METATYPE (MessageServer::ClientKey); + #endif diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2668a6021..b7620ec90 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -41,15 +41,17 @@ class Client { Q_OBJECT + using ClientKey = MessageServer::ClientKey; + public: - explicit Client (QString const& id, QObject * parent = nullptr) + explicit Client (ClientKey const& key, QObject * parent = nullptr) : QObject {parent} - , id_ {id} + , key_ {key} , dial_frequency_ {0u} { } - Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& /*dx_call*/ + Q_SLOT void update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& /*dx_call*/ , QString const& /*report*/, QString const& /*tx_mode*/, bool /*tx_enabled*/ , bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*tx_df*/ , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ @@ -57,67 +59,73 @@ public: , quint8 /*special_op_mode*/, quint32 /*frequency_tolerance*/, quint32 /*tr_period*/ , QString const& /*configuration_name*/) { - if (id == id_) + if (key == key_) { if (f != dial_frequency_) { - std::cout << tr ("%1: Dial frequency changed to %2").arg (id_).arg (f).toStdString () << std::endl; + std::cout << tr ("%1(%2): Dial frequency changed to %3") + .arg (key_.second).arg (key_.first.toString ()).arg (f).toStdString () << std::endl; dial_frequency_ = f; } if (mode + sub_mode != mode_) { - std::cout << tr ("%1: Mode changed to %2").arg (id_).arg (mode + sub_mode).toStdString () << std::endl; + std::cout << tr ("%1(%2): Mode changed to %3") + .arg (key_.second).arg (key_.first.toString ()).arg (mode + sub_mode).toStdString () << std::endl; mode_ = mode + sub_mode; } } } - Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime time, qint32 snr + Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime time, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air) { - if (client_id == id_) + if (key == key_) { qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high") << "On air:" << !off_air; - std::cout << tr ("%1: Decoded %2").arg (id_).arg (message).toStdString () << std::endl; + std::cout << tr ("%1(%2): Decoded %3") + .arg (key_.second).arg (key_.first.toString ()).arg (message).toStdString () << std::endl; } } - Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime time, qint32 snr + Q_SLOT void beacon_spot_added (bool is_new, ClientKey const& key, QTime time, qint32 snr , float delta_time, Frequency delta_frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { - if (client_id == id_) + if (key == key_) { qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "drift:" << drift; - std::cout << tr ("%1: WSPR decode %2 grid %3 power: %4").arg (id_).arg (callsign).arg (grid).arg (power).toStdString () + std::cout << tr ("%1(%2): WSPR decode %3 grid %4 power: %5") + .arg (key_.second).arg (key_.first.toString ()).arg (callsign).arg (grid).arg (power).toStdString () << "On air:" << !off_air << std::endl; } } - Q_SLOT void qso_logged (QString const&client_id, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SLOT void qso_logged (ClientKey const& key, QDateTime time_off, QString const& dx_call, QString const& dx_grid , Frequency dial_frequency, QString const& mode, QString const& report_sent , QString const& report_received, QString const& tx_power , QString const& comments, QString const& name, QDateTime time_on , QString const& operator_call, QString const& my_call, QString const& my_grid , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode) { - if (client_id == id_) + if (key == key_) { - qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" << dx_call << "grid:" << dx_grid + qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" + << dx_call << "grid:" << dx_grid << "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent << "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments << "name:" << name << "operator_call:" << operator_call << "my_call:" << my_call << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent << "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode; std::cout << QByteArray {80, '-'}.data () << '\n'; - std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 time_off: %8 op: %9 my_call: %10 my_grid: %11 exchange_sent: %12 exchange_rcvd: %13 comments: %14 prop_mode: %15") - .arg (id_).arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received) + std::cout << tr ("%1(%2): Logged %3 grid: %4 power: %5 sent: %6 recd: %7 freq: %8 time_off: %9 op: %10 my_call: %11 my_grid: %12 exchange_sent: %13 exchange_rcvd: %14 comments: %15 prop_mode: %16") + .arg (key_.second).arg (key.first.toString ()).arg (dx_call).arg (dx_grid).arg (tx_power) + .arg (report_sent).arg (report_received) .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) .arg (comments).arg (prop_mode).toStdString () @@ -125,9 +133,9 @@ public: } } - Q_SLOT void logged_ADIF (QString const&client_id, QByteArray const& ADIF) + Q_SLOT void logged_ADIF (ClientKey const& key, QByteArray const& ADIF) { - if (client_id == id_) + if (key == key_) { qDebug () << "ADIF:" << ADIF; std::cout << QByteArray {80, '-'}.data () << '\n'; @@ -136,7 +144,7 @@ public: } private: - QString id_; + ClientKey key_; Frequency dial_frequency_; QString mode_; }; @@ -146,6 +154,8 @@ class Server { Q_OBJECT + using ClientKey = MessageServer::ClientKey; + public: Server (port_type port, QHostAddress const& multicast_group, QStringList const& network_interface_names) : server_ {new MessageServer {this}} @@ -161,17 +171,18 @@ public: } private: - void add_client (QString const& id, QString const& version, QString const& revision) + void add_client (ClientKey const& key, QString const& version, QString const& revision) { - auto client = new Client {id}; + auto client = new Client {key}; connect (server_, &MessageServer::status_update, client, &Client::update_status); connect (server_, &MessageServer::decode, client, &Client::decode_added); connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added); connect (server_, &MessageServer::qso_logged, client, &Client::qso_logged); connect (server_, &MessageServer::logged_ADIF, client, &Client::logged_ADIF); - clients_[id] = client; - server_->replay (id); - std::cout << "Discovered WSJT-X instance: " << id.toStdString (); + clients_[key] = client; + server_->replay (key); + std::cout << "Discovered WSJT-X instance: " << key.second.toStdString () + << '(' << key.first.toString ().toStdString () << ')'; if (version.size ()) { std::cout << " v" << version.toStdString (); @@ -183,21 +194,22 @@ private: std::cout << std::endl; } - void remove_client (QString const& id) + void remove_client (ClientKey const& key) { - auto iter = clients_.find (id); + auto iter = clients_.find (key); if (iter != std::end (clients_)) { clients_.erase (iter); (*iter)->deleteLater (); } - std::cout << "Removed WSJT-X instance: " << id.toStdString () << std::endl; + std::cout << "Removed WSJT-X instance: " << key.second.toStdString () + << '(' << key.first.toString ().toStdString () << ')' << std::endl; } MessageServer * server_; - // maps client id to clients - QHash clients_; + // maps client key to clients + QHash clients_; }; #include "UDPDaemon.moc" From 014812e6c6767ec88afb817027e13f748cfc1dc9 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 2 Nov 2020 22:08:37 +0000 Subject: [PATCH 31/73] UDPDaemon command line flag to list network interfaces --- UDPExamples/UDPDaemon.cpp | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index b7620ec90..2044bfb00 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -17,12 +17,14 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -212,6 +214,42 @@ private: QHash clients_; }; +void list_interfaces () +{ + for (auto const& net_if : QNetworkInterface::allInterfaces ()) + { + if (net_if.flags () & QNetworkInterface::IsUp) + { + std::cout << net_if.humanReadableName ().toStdString () << ":\n" + " id: " << net_if.name ().toStdString () << " (" << net_if.index () << ")\n" + " addr: " << net_if.hardwareAddress ().toStdString () << "\n" + " flags: "; + if (net_if.flags () & QNetworkInterface::IsRunning) + { + std::cout << "Running "; + } + if (net_if.flags () & QNetworkInterface::CanBroadcast) + { + std::cout << "Broadcast "; + } + if (net_if.flags () & QNetworkInterface::CanMulticast) + { + std::cout << "Multicast "; + } + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + std::cout << "Loop-back "; + } + std::cout << "\n addresses:\n"; + for (auto const& ae : net_if.addressEntries ()) + { + std::cout << " " << ae.ip ().toString ().toStdString () << '\n'; + } + std::cout << '\n'; + } + } +} + #include "UDPDaemon.moc" int main (int argc, char * argv[]) @@ -232,6 +270,11 @@ int main (int argc, char * argv[]) auto help_option = parser.addHelpOption (); auto version_option = parser.addVersionOption (); + QCommandLineOption list_option (QStringList {"l", "list-interfaces"}, + app.translate ("UDPDaemon", + "Print the available network interfaces.")); + parser.addOption (list_option); + QCommandLineOption port_option (QStringList {"p", "port"}, app.translate ("UDPDaemon", "Where is the UDP service port number to listen on.\n" @@ -257,6 +300,12 @@ int main (int argc, char * argv[]) parser.process (app); + if (parser.isSet (list_option)) + { + list_interfaces (); + return EXIT_SUCCESS; + } + Server server {static_cast (parser.value (port_option).toUInt ()) , QHostAddress {parser.value (multicast_addr_option).trimmed ()} , parser.values (network_interface_option)}; From 8516a4f5383dd8e5713ee7ed21bdc6dc1b215717 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 20:28:29 +0000 Subject: [PATCH 32/73] New combo box with a list of checkable items --- CMakeLists.txt | 1 + widgets/CheckableItemComboBox.cpp | 93 +++++++++++++++++++++++++++++++ widgets/CheckableItemComboBox.hpp | 36 ++++++++++++ widgets/widgets.pri | 7 ++- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 widgets/CheckableItemComboBox.cpp create mode 100644 widgets/CheckableItemComboBox.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dc5b0823..77cfa3377 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,7 @@ set (wsjt_qt_CXXSRCS logbook/Multiplier.cpp Network/NetworkAccessManager.cpp widgets/LazyFillComboBox.cpp + widgets/CheckableItemComboBox.cpp ) set (wsjt_qtmm_CXXSRCS diff --git a/widgets/CheckableItemComboBox.cpp b/widgets/CheckableItemComboBox.cpp new file mode 100644 index 000000000..3ef926243 --- /dev/null +++ b/widgets/CheckableItemComboBox.cpp @@ -0,0 +1,93 @@ +#include "CheckableItemComboBox.hpp" + +#include +#include +#include +#include +#include +#include + +class CheckableItemComboBoxStyledItemDelegate + : public QStyledItemDelegate +{ +public: + explicit CheckableItemComboBoxStyledItemDelegate (QObject * parent = nullptr) + : QStyledItemDelegate {parent} + { + } + + void paint (QPainter * painter, QStyleOptionViewItem const& option, QModelIndex const& index) const override + { + QStyleOptionViewItem& mutable_option = const_cast (option); + mutable_option.showDecorationSelected = false; + QStyledItemDelegate::paint (painter, mutable_option, index); + } +}; + +CheckableItemComboBox::CheckableItemComboBox (QWidget * parent) + : QComboBox {parent} + , model_ {new QStandardItemModel()} +{ + setModel (model_.data ()); + + setEditable (true); + lineEdit ()->setReadOnly (true); + lineEdit ()->installEventFilter (this); + setItemDelegate (new CheckableItemComboBoxStyledItemDelegate {this}); + + connect (lineEdit(), &QLineEdit::selectionChanged, lineEdit(), &QLineEdit::deselect); + connect (static_cast (view ()), &QListView::pressed, this, &CheckableItemComboBox::item_pressed); + connect (model_.data (), &QStandardItemModel::dataChanged, this, &CheckableItemComboBox::model_data_changed); +} + +QStandardItem * CheckableItemComboBox::addCheckItem (QString const& label, QVariant const& data + , Qt::CheckState checkState) +{ + auto * item = new QStandardItem {label}; + item->setCheckState (checkState); + item->setData (data); + item->setFlags (Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + model_->appendRow (item); + update_text (); + return item; +} + +bool CheckableItemComboBox::eventFilter (QObject * object, QEvent * event) +{ + if (object == lineEdit() && event->type () == QEvent::MouseButtonPress) + { + showPopup(); + return true; + } + return false; +} + +void CheckableItemComboBox::update_text() +{ + QString text; + for (int i = 0; i < model_->rowCount (); ++i) + { + if (model_->item (i)->checkState () == Qt::Checked) + { + if (text.size ()) + { + text+= ", "; + } + text += model_->item (i)->data ().toString (); + } + } + lineEdit ()->setText (text); +} + +void CheckableItemComboBox::model_data_changed () +{ + update_text (); +} + +void CheckableItemComboBox::item_pressed (QModelIndex const& index) +{ + QStandardItem * item = model_->itemFromIndex (index); + item->setCheckState (item->checkState () == Qt::Checked ? Qt::Unchecked : Qt::Checked); +} + +#include "widgets/moc_CheckableItemComboBox.cpp" diff --git a/widgets/CheckableItemComboBox.hpp b/widgets/CheckableItemComboBox.hpp new file mode 100644 index 000000000..2aa3e9831 --- /dev/null +++ b/widgets/CheckableItemComboBox.hpp @@ -0,0 +1,36 @@ +#ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__ +#define CHECKABLE_ITEM_COMBO_BOX_HPP__ + +#include +#include + +class QStandardItemModel; +class QStandardItem; + +/** + * @brief QComboBox with support of checkboxes + * http://stackoverflow.com/questions/8422760/combobox-of-checkboxes + */ +class CheckableItemComboBox + : public QComboBox +{ + Q_OBJECT + +public: + explicit CheckableItemComboBox (QWidget * parent = nullptr); + QStandardItem * addCheckItem (QString const& label, QVariant const& data, Qt::CheckState checkState); + +protected: + bool eventFilter (QObject *, QEvent *) override; + +private: + void update_text(); + + Q_SLOT void model_data_changed (); + Q_SLOT void item_pressed (QModelIndex const&); + +private: + QScopedPointer model_; +}; + +#endif diff --git a/widgets/widgets.pri b/widgets/widgets.pri index 7a364c4ee..6a623d825 100644 --- a/widgets/widgets.pri +++ b/widgets/widgets.pri @@ -10,7 +10,9 @@ SOURCES += \ widgets/AbstractLogWindow.cpp \ widgets/FrequencyLineEdit.cpp widgets/FrequencyDeltaLineEdit.cpp \ widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp \ - widgets/HelpTextWindow.cpp widgets/RestrictedSpinBox.cpp + widgets/HelpTextWindow.cpp widgets/RestrictedSpinBox.cpp \ + widgets/LazyFillComboBox.cpp widgets/CheckableItemComboBox.cpp + HEADERS += \ widgets/mainwindow.h widgets/plotter.h \ widgets/about.h widgets/widegraph.h \ @@ -22,7 +24,8 @@ HEADERS += \ widgets/ExportCabrillo.h widgets/AbstractLogWindow.hpp \ widgets/FoxLogWindow.hpp widgets/CabrilloLogWindow.hpp \ widgets/DateTimeEdit.hpp widgets/HelpTextWindow.hpp \ - widgets/RestrictedSpinBox.hpp + widgets/RestrictedSpinBox.hpp \ + widgets/LazyFillComboBox.hpp widgets/CheckableItemComboBox.hpp FORMS += \ widgets/mainwindow.ui widgets/about.ui \ From 1a223f5c45c4d33c7e46e4eb9a1aa7894204517b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 20:29:25 +0000 Subject: [PATCH 33/73] Remove unwanted file and directory --- lib/fsk4hf/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/fsk4hf/.DS_Store diff --git a/lib/fsk4hf/.DS_Store b/lib/fsk4hf/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Tue, 3 Nov 2020 20:31:11 +0000 Subject: [PATCH 34/73] Add network interface selection combo box widget to message_aggregator --- CMakeLists.txt | 2 +- UDPExamples/MessageAggregatorMainWindow.cpp | 96 ++++++++++++++++++--- UDPExamples/MessageAggregatorMainWindow.hpp | 7 ++ UDPExamples/MessageServer.cpp | 10 ++- UDPExamples/MessageServer.hpp | 4 +- UDPExamples/UDPDaemon.cpp | 2 +- 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 77cfa3377..c7fd14434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1491,7 +1491,7 @@ add_executable (message_aggregator ${message_aggregator_RESOURCES_RCC} ${message_aggregator_VERSION_RESOURCES} ) -target_link_libraries (message_aggregator Qt5::Widgets wsjtx_udp-static) +target_link_libraries (message_aggregator wsjt_qt Qt5::Widgets wsjtx_udp-static) if (WSJT_CREATE_WINMAIN) set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON) diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index 7e74342c0..d110bfc44 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include "DecodesModel.hpp" #include "BeaconsModel.hpp" @@ -37,8 +39,10 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () , decodes_model_ {new DecodesModel {this}} , beacons_model_ {new BeaconsModel {this}} , server_ {new MessageServer {this}} - , multicast_group_line_edit_ {new QLineEdit} - , log_table_view_ {new QTableView} + , port_spin_box_ {new QSpinBox {this}} + , multicast_group_line_edit_ {new QLineEdit {this}} + , network_interfaces_combo_box_ {new CheckableItemComboBox {this}} + , log_table_view_ {new QTableView {this}} , add_call_of_interest_action_ {new QAction {tr ("&Add callsign"), this}} , delete_call_of_interest_action_ {new QAction {tr ("&Delete callsign"), this}} , last_call_of_interest_action_ {new QAction {tr ("&Highlight last only"), this}} @@ -68,16 +72,66 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () auto central_layout = new QVBoxLayout; // server details - auto port_spin_box = new QSpinBox; - port_spin_box->setMinimum (1); - port_spin_box->setMaximum (std::numeric_limits::max ()); + port_spin_box_->setMinimum (1); + port_spin_box_->setMaximum (std::numeric_limits::max ()); auto group_box_layout = new QFormLayout; - group_box_layout->addRow (tr ("Port number:"), port_spin_box); + group_box_layout->addRow (tr ("Port number:"), port_spin_box_); group_box_layout->addRow (tr ("Multicast Group (blank for unicast server):"), multicast_group_line_edit_); + group_box_layout->addRow (tr ("Network interfaces:"), network_interfaces_combo_box_); + int row; + QFormLayout::ItemRole role; + group_box_layout->getWidgetPosition (network_interfaces_combo_box_, &row, &role); + Q_ASSERT (row >= 0); + network_interfaces_form_label_widget_ = static_cast (group_box_layout->itemAt (row, QFormLayout::LabelRole)->widget ()); + network_interfaces_form_label_widget_->hide (); + network_interfaces_form_label_widget_->buddy ()->hide (); + connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this] { + if (multicast_group_line_edit_->text ().size ()) + { + network_interfaces_form_label_widget_->show (); + network_interfaces_form_label_widget_->buddy ()->show (); + } + else + { + network_interfaces_form_label_widget_->hide (); + network_interfaces_form_label_widget_->buddy ()->hide (); + } + }); auto group_box = new QGroupBox {tr ("Server Details")}; group_box->setLayout (group_box_layout); central_layout->addWidget (group_box); + // populate network interface list + for (auto const& net_if : QNetworkInterface::allInterfaces ()) + { + auto flags = QNetworkInterface::IsRunning | QNetworkInterface::CanMulticast; + if ((net_if.flags () & flags) == flags) + { + auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + auto item = network_interfaces_combo_box_->addCheckItem (net_if.humanReadableName () + , net_if.name () + , is_loopback ? Qt::Checked : Qt::Unchecked); + item->setEnabled (!is_loopback); + auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) + .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); + auto hw_addr = net_if.hardwareAddress (); + if (hw_addr.size ()) + { + tip += QString {"\nhw: %1"}.arg (net_if.hardwareAddress ()); + } + auto aes = net_if.addressEntries (); + if (aes.size ()) + { + tip += "\naddresses:"; + for (auto const& ae : aes) + { + tip += QString {"\n ip: %1/%2"}.arg (ae.ip ().toString ()).arg (ae.prefixLength ()); + } + } + item->setToolTip (tip); + } + } + log_table_view_->setModel (log_); log_table_view_->verticalHeader ()->hide (); central_layout->addWidget (log_table_view_); @@ -200,16 +254,34 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () connect (decodes_model_, &DecodesModel::reply, server_, &MessageServer::reply); // UI behaviour - connect (port_spin_box, static_cast (&QSpinBox::valueChanged) - , [this] (port_type port) {server_->start (port);}); - connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this, port_spin_box] () { - server_->start (port_spin_box->value (), QHostAddress {multicast_group_line_edit_->text ()}); - }); + connect (port_spin_box_, static_cast (&QSpinBox::valueChanged) + , [this] (int /*port*/) {restart_server ();}); + connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this] () {restart_server ();}); + connect (network_interfaces_combo_box_, &QComboBox::currentTextChanged, [this] () {restart_server ();}); - port_spin_box->setValue (2237); // start up in unicast mode + port_spin_box_->setValue (2237); // start up in unicast mode show (); } +void MessageAggregatorMainWindow::restart_server () +{ + QSet net_ifs; + if (network_interfaces_combo_box_->isVisible ()) + { + auto model = static_cast (network_interfaces_combo_box_->model ()); + for (int row = 0; row < model->rowCount (); ++row) + { + if (Qt::Checked == model->item (row)->checkState ()) + { + net_ifs << model->item (row)->data ().toString (); + } + } + } + server_->start (port_spin_box_->value () + , QHostAddress {multicast_group_line_edit_->text ()} + , net_ifs); +} + void MessageAggregatorMainWindow::log_qso (ClientKey const& /*key*/, QDateTime time_off , QString const& dx_call , QString const& dx_grid, Frequency dial_frequency, QString const& mode diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 445a5908e..1bff0d692 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -6,6 +6,7 @@ #include #include "MessageServer.hpp" +#include "widgets/CheckableItemComboBox.hpp" class QDateTime; class QStandardItemModel; @@ -16,6 +17,8 @@ class QLineEdit; class QTableView; class ClientWidget; class QListWidget; +class QLabel; +class QSpinBox; using Frequency = MessageServer::Frequency; @@ -38,6 +41,7 @@ public: , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); private: + void restart_server (); void add_client (ClientKey const&, QString const& version, QString const& revision); void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, @@ -52,7 +56,10 @@ private: DecodesModel * decodes_model_; BeaconsModel * beacons_model_; MessageServer * server_; + QSpinBox * port_spin_box_; QLineEdit * multicast_group_line_edit_; + CheckableItemComboBox * network_interfaces_combo_box_; + QLabel * network_interfaces_form_label_widget_; QTableView * log_table_view_; QListWidget * calls_of_interest_; QAction * add_call_of_interest_action_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 8869c4b89..6745fe0a7 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -78,7 +77,7 @@ public: QString version_; QString revision_; QHostAddress multicast_group_address_; - QStringList network_interfaces_; + QSet network_interfaces_; static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint; struct Client { @@ -433,9 +432,12 @@ MessageServer::MessageServer (QObject * parent, QString const& version, QString } void MessageServer::start (port_type port, QHostAddress const& multicast_group_address - , QStringList const& network_interface_names) + , QSet const& network_interface_names) { - if (port != m_->localPort () || multicast_group_address != m_->multicast_group_address_) + qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names; + if (port != m_->localPort () + || multicast_group_address != m_->multicast_group_address_ + || network_interface_names != m_->network_interfaces_) { m_->leave_multicast_group (); if (impl::UnconnectedState != m_->state ()) diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 8a31e7bd5..7cf5653a0 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,7 +44,7 @@ public: // which the server will join Q_SLOT void start (port_type port , QHostAddress const& multicast_group_address = QHostAddress {} - , QStringList const& network_interface_names = QStringList {}); + , QSet const& network_interface_names = QSet {}); // ask the client to clear one or both of the decode windows Q_SLOT void clear_decodes (ClientKey const&, quint8 window = 0); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2044bfb00..0f6793028 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -169,7 +169,7 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); - server_->start (port, multicast_group, network_interface_names); + server_->start (port, multicast_group, QSet {network_interface_names.begin (), network_interface_names.end ()}); } private: From a6a176bf6e59c718d815285ff495635008c48c8c Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:07:38 +0000 Subject: [PATCH 35/73] Pre Qt v5.11 compatibility --- qt_helpers.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/qt_helpers.hpp b/qt_helpers.hpp index 7170bda0b..034a8852f 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -117,6 +117,16 @@ namespace std } #endif +inline +bool is_broadcast_address (QHostAddress const& host_addr) +{ +#if QT_VERSION >= 0x051100 + return host_addr.isBroadcast (); +#else + bool ok; + return host_addr.toIPv4Address (&ok) == 0xffffffffu && ok; +#endif +} inline bool is_multicast_address (QHostAddress const& host_addr) From 698bd23a9cc2755005bbb26694ce2470de874e27 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:08:12 +0000 Subject: [PATCH 36/73] Disallow sending UDP Message Protocol traffic to broadcast address --- Network/MessageClient.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 57ffb2806..3474f19bb 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -148,6 +148,13 @@ void MessageClient::impl::start () return; } + if (is_broadcast_address (server_)) + { + Q_EMIT self_->error ("IPv4 broadcast not supported, please specify the loop-back address, a server host address, or multicast group address"); + pending_messages_.clear (); // discard + return; + } + if (blocked_addresses_.end () != std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server_)) { Q_EMIT self_->error ("UDP server blocked, please try another"); @@ -181,13 +188,6 @@ void MessageClient::impl::start () } } - if (server_.isBroadcast ()) - { - // only allow broadcast on the loopback interface to avoid - // flooding the local subnet which may be large with some ISPs - //interface_ip.setAddress ("127.0.0.1"); - } - if (localAddress () != interface_ip) { if (UnconnectedState != state () || state ()) From d70cf120b56c1045106c769095740155aa5f611b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:14:26 +0000 Subject: [PATCH 37/73] Pre Qt 5.14 compatibility --- UDPExamples/UDPDaemon.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 0f6793028..6d98b3a6b 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -169,7 +169,11 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); +#if QT_VERSION >= 0x051400 server_->start (port, multicast_group, QSet {network_interface_names.begin (), network_interface_names.end ()}); +#else + server_->start (port, multicast_group, network_interface_names.toSet ()); +#endif } private: From 11497cf0b1d7d1ee4918003ac2b812750fece8ed Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:44:07 +0000 Subject: [PATCH 38/73] Correct Qt version checks --- Network/NetworkMessage.cpp | 8 ++++---- Network/NetworkMessage.hpp | 4 ++-- UDPExamples/UDPDaemon.cpp | 2 +- qt_helpers.hpp | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Network/NetworkMessage.cpp b/Network/NetworkMessage.cpp index 5af133c7f..a1e7050f2 100644 --- a/Network/NetworkMessage.cpp +++ b/Network/NetworkMessage.cpp @@ -28,13 +28,13 @@ namespace NetworkMessage { setVersion (QDataStream::Qt_5_0); // Qt schema version } -#if QT_VERSION >= 0x050200 +#if QT_VERSION >= QT_VERSION_CHECK (5, 2, 0) else if (schema <= 2) { setVersion (QDataStream::Qt_5_2); // Qt schema version } #endif -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 4, 0) else if (schema <= 3) { setVersion (QDataStream::Qt_5_4); // Qt schema version @@ -73,13 +73,13 @@ namespace NetworkMessage { parent->setVersion (QDataStream::Qt_5_0); } -#if QT_VERSION >= 0x050200 +#if QT_VERSION >= QT_VERSION_CHECK (5, 2, 0) else if (schema_ <= 2) { parent->setVersion (QDataStream::Qt_5_2); } #endif -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 4, 0) else if (schema_ <= 3) { parent->setVersion (QDataStream::Qt_5_4); diff --git a/Network/NetworkMessage.hpp b/Network/NetworkMessage.hpp index c484efb23..f892eda06 100644 --- a/Network/NetworkMessage.hpp +++ b/Network/NetworkMessage.hpp @@ -540,9 +540,9 @@ namespace NetworkMessage // increment this if a newer Qt schema is required and add decode // logic to the Builder and Reader class implementations -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 4, 0) static quint32 constexpr schema_number {3}; -#elif QT_VERSION >= 0x050200 +#elif QT_VERSION >= QT_VERSION_CHECK (5, 2, 0) static quint32 constexpr schema_number {2}; #else // Schema 1 (Qt_5_0) is broken diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 6d98b3a6b..78d1a0c52 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -169,7 +169,7 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); -#if QT_VERSION >= 0x051400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 14, 0) server_->start (port, multicast_group, QSet {network_interface_names.begin (), network_interface_names.end ()}); #else server_->start (port, multicast_group, network_interface_names.toSet ()); diff --git a/qt_helpers.hpp b/qt_helpers.hpp index 034a8852f..416b6421b 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -120,7 +120,7 @@ namespace std inline bool is_broadcast_address (QHostAddress const& host_addr) { -#if QT_VERSION >= 0x051100 +#if QT_VERSION >= QT_VERSION_CHECK (5, 11, 0) return host_addr.isBroadcast (); #else bool ok; @@ -131,7 +131,7 @@ bool is_broadcast_address (QHostAddress const& host_addr) inline bool is_multicast_address (QHostAddress const& host_addr) { -#if QT_VERSION >= 0x050600 +#if QT_VERSION >= QT_VERSION_CHECK (5, 6, 0) return host_addr.isMulticast (); #else bool ok; From 3bc31030043bd851329e2b3bc704a76dd402aa56 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 4 Nov 2020 16:02:04 +0000 Subject: [PATCH 39/73] UDP multicast TTL default as one Restricts scope to local subnet. --- Configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration.cpp b/Configuration.cpp index fac5564ab..78f3dafa6 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -1546,7 +1546,7 @@ void Configuration::impl::read_settings () opCall_ = settings_->value ("OpCall", "").toString (); udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString (); udp_interface_name_ = settings_->value ("UDPInterface").toString (); - udp_TTL_ = settings_->value ("UDPTTL").toInt (); + udp_TTL_ = settings_->value ("UDPTTL", 1).toInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString (); n1mm_server_port_ = settings_->value ("N1MMServerPort", 2333).toUInt (); From caa23f1101aab318df437a64545341e0147839ae Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 5 Nov 2020 03:37:01 +0000 Subject: [PATCH 40/73] Message Client allows sending multicast UDP on multiple interfaces --- Configuration.cpp | 87 ++++++++++++------- Configuration.hpp | 6 +- Configuration.ui | 21 +++-- Network/MessageClient.cpp | 92 ++++++++------------- Network/MessageClient.hpp | 4 +- UDPExamples/MessageAggregatorMainWindow.cpp | 22 ++--- UDPExamples/UDPDaemon.cpp | 30 +++---- widgets/CheckableItemComboBox.cpp | 2 +- widgets/CheckableItemComboBox.hpp | 5 +- widgets/LazyFillComboBox.hpp | 2 +- widgets/mainwindow.cpp | 4 +- 11 files changed, 145 insertions(+), 130 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 78f3dafa6..7f68bb417 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -166,6 +166,7 @@ #include #include #include +#include #include #include "pimpl_impl.hpp" @@ -442,7 +443,8 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); - void load_network_interfaces (QComboBox *, QString const& current); + void load_network_interfaces (CheckableItemComboBox *, QStringList const& current); + QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -653,7 +655,7 @@ private: bool udp_server_name_edited_; int dns_lookup_id_; port_type udp_server_port_; - QString udp_interface_name_; + QStringList udp_interface_names_; int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; @@ -754,7 +756,7 @@ QString Configuration::opCall() const {return m_->opCall_;} void Configuration::opCall (QString const& call) {m_->opCall_ = call;} QString Configuration::udp_server_name () const {return m_->udp_server_name_;} auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;} -QString Configuration::udp_interface_name () const {return m_->udp_interface_name_;} +QStringList Configuration::udp_interface_names () const {return m_->udp_interface_names_;} int Configuration::udp_TTL () const {return m_->udp_TTL_;} bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;} QString Configuration::n1mm_server_name () const {return m_->n1mm_server_name_;} @@ -1078,9 +1080,9 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network }); // set up dynamic loading of network interfaces - connect (ui_->udp_interface_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { + connect (ui_->udp_interfaces_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor}); - load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); + load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); @@ -1362,10 +1364,10 @@ void Configuration::impl::initialize_models () ui_->udp_server_line_edit->setText (udp_server_name_); on_udp_server_line_edit_editingFinished (); ui_->udp_server_port_spin_box->setValue (udp_server_port_); - load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); - if (!udp_interface_name_.size ()) + load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); + if (!udp_interface_names_.size ()) { - udp_interface_name_ = ui_->udp_interface_combo_box->currentData ().toString (); + udp_interface_names_ = get_selected_network_interfaces (ui_->udp_interfaces_combo_box); } ui_->udp_TTL_spin_box->setValue (udp_TTL_); ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_); @@ -1545,7 +1547,7 @@ void Configuration::impl::read_settings () rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value (); opCall_ = settings_->value ("OpCall", "").toString (); udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString (); - udp_interface_name_ = settings_->value ("UDPInterface").toString (); + udp_interface_names_ = settings_->value ("UDPInterface").toStringList (); udp_TTL_ = settings_->value ("UDPTTL", 1).toInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString (); @@ -1675,7 +1677,7 @@ void Configuration::impl::write_settings () settings_->setValue ("OpCall", opCall_); settings_->setValue ("UDPServer", udp_server_name_); settings_->setValue ("UDPServerPort", udp_server_port_); - settings_->setValue ("UDPInterface", udp_interface_name_); + settings_->setValue ("UDPInterface", QVariant::fromValue (udp_interface_names_)); settings_->setValue ("UDPTTL", udp_TTL_); settings_->setValue ("N1MMServer", n1mm_server_name_); settings_->setValue ("N1MMServerPort", n1mm_server_port_); @@ -2105,12 +2107,12 @@ void Configuration::impl::accept () opCall_=ui_->opCallEntry->text(); auto new_server = ui_->udp_server_line_edit->text ().trimmed (); - auto new_interface = ui_->udp_interface_combo_box->currentData ().toString (); - if (new_server != udp_server_name_ || new_interface != udp_interface_name_) + auto new_interfaces = get_selected_network_interfaces (ui_->udp_interfaces_combo_box); + if (new_server != udp_server_name_ || new_interfaces != udp_interface_names_) { udp_server_name_ = new_server; - udp_interface_name_ = new_interface; - Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_name_); + udp_interface_names_ = new_interfaces; + Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_names_); } auto new_port = ui_->udp_server_port_spin_box->value (); @@ -2452,8 +2454,8 @@ void Configuration::impl::host_info_results (QHostInfo host_info) void Configuration::impl::check_multicast (QHostAddress const& ha) { auto is_multicast = is_multicast_address (ha); - ui_->udp_interface_label->setVisible (is_multicast); - ui_->udp_interface_combo_box->setVisible (is_multicast); + ui_->udp_interfaces_label->setVisible (is_multicast); + ui_->udp_interfaces_combo_box->setVisible (is_multicast); ui_->udp_TTL_label->setVisible (is_multicast); ui_->udp_TTL_spin_box->setVisible (is_multicast); if (isVisible ()) @@ -2993,28 +2995,53 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com } // load the available network interfaces into the selection combo box -void Configuration::impl::load_network_interfaces (QComboBox * combo_box, QString const& current) +void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList const& current) { combo_box->clear (); - int current_index = -1; - for (auto const& interface : QNetworkInterface::allInterfaces ()) + for (auto const& net_if : QNetworkInterface::allInterfaces ()) { - if (interface.flags () & QNetworkInterface::IsUp) + auto flags = QNetworkInterface::IsUp | QNetworkInterface::CanMulticast; + if ((net_if.flags () & flags) == flags) { - auto const& name = interface.name (); - combo_box->addItem (interface.humanReadableName (), name); - // select the first loopback interface as a default to - // discourage spamming the network (possibly the Internet), - // particularly important with administratively scoped - // multicast UDP - if (name == current - || (!current.size () && (interface.flags () & QNetworkInterface::IsLoopBack))) + auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + auto item = combo_box->addCheckItem (net_if.humanReadableName () + , net_if.name () + , is_loopback || current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); + item->setEnabled (!is_loopback); + auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) + .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); + auto hw_addr = net_if.hardwareAddress (); + if (hw_addr.size ()) { - current_index = combo_box->count () - 1; + tip += QString {"\nhw: %1"}.arg (net_if.hardwareAddress ()); } + auto aes = net_if.addressEntries (); + if (aes.size ()) + { + tip += "\naddresses:"; + for (auto const& ae : aes) + { + tip += QString {"\n ip: %1/%2"}.arg (ae.ip ().toString ()).arg (ae.prefixLength ()); + } + } + item->setToolTip (tip); } } - combo_box->setCurrentIndex (current_index); +} + +// get the select network interfaces from the selection combo box +QStringList Configuration::impl::get_selected_network_interfaces (CheckableItemComboBox * combo_box) +{ + QStringList interfaces; + auto model = static_cast (combo_box->model ()); + for (int row = 0; row < model->rowCount (); ++row) + { + if (Qt::Checked == model->item (row)->checkState ()) + { + interfaces << model->item (row)->data ().toString (); + } + } + return interfaces; } // enable only the channels that are supported by the selected audio device diff --git a/Configuration.hpp b/Configuration.hpp index 403673663..b0f6bf75b 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "Radio.hpp" #include "models/IARURegions.hpp" @@ -14,7 +15,6 @@ class QSettings; class QWidget; class QAudioDeviceInfo; -class QString; class QDir; class QNetworkAccessManager; class Bands; @@ -151,7 +151,7 @@ public: void opCall (QString const&); QString udp_server_name () const; port_type udp_server_port () const; - QString udp_interface_name () const; + QStringList udp_interface_names () const; int udp_TTL () const; QString n1mm_server_name () const; port_type n1mm_server_port () const; @@ -274,7 +274,7 @@ public: // // This signal is emitted when the UDP server changes // - Q_SIGNAL void udp_server_changed (QString& udp_server_name, QString const& network_interface) const; + Q_SIGNAL void udp_server_changed (QString& udp_server_name, QStringList const& network_interfaces) const; Q_SIGNAL void udp_server_port_changed (port_type server_port) const; Q_SIGNAL void udp_TTL_changed (int TTL) const; Q_SIGNAL void accept_udp_requests_changed (bool checked) const; diff --git a/Configuration.ui b/Configuration.ui index fd8fb8955..1b6ef8926 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -1893,17 +1893,17 @@ and DX Grid fields when a 73 or free text message is sent. - + - Outgoing interface: + Outgoing interfaces: - udp_interface_combo_box + udp_interfaces_combo_box - + @@ -3029,6 +3029,11 @@ Right click for insert and delete options. QComboBox
widgets/LazyFillComboBox.hpp
+ + CheckableItemComboBox + QComboBox +
widgets/CheckableItemComboBox.hpp
+
configuration_tabs @@ -3111,7 +3116,7 @@ Right click for insert and delete options. psk_reporter_tcpip_check_box udp_server_line_edit udp_server_port_spin_box - udp_interface_combo_box + udp_interfaces_combo_box udp_TTL_spin_box accept_udp_requests_check_box udpWindowToFront @@ -3221,13 +3226,13 @@ Right click for insert and delete options. - + - + - + diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 3474f19bb..2e721d5f7 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -59,7 +59,7 @@ public: enum StreamStatus {Fail, Short, OK}; - void set_server (QString const& server_name, QString const& network_interface_name); + void set_server (QString const& server_name, QStringList const& network_interface_names); Q_SLOT void host_info_results (QHostInfo); void start (); void parse_message (QByteArray const&); @@ -67,12 +67,12 @@ public: void heartbeat (); void closedown (); StreamStatus check_status (QDataStream const&) const; - void send_message (QByteArray const&); - void send_message (QDataStream const& out, QByteArray const& message) + void send_message (QByteArray const&, bool queue_if_pending = true); + void send_message (QDataStream const& out, QByteArray const& message, bool queue_if_pending = true) { if (OK == check_status (out)) { - send_message (message); + send_message (message, queue_if_pending); } else { @@ -89,7 +89,7 @@ public: QHostAddress server_; port_type server_port_; int TTL_; - QNetworkInterface network_interface_; + std::vector network_interfaces_; quint32 schema_; QTimer * heartbeat_timer_; std::vector blocked_addresses_; @@ -101,10 +101,15 @@ public: #include "MessageClient.moc" -void MessageClient::impl::set_server (QString const& server_name, QString const& network_interface_name) +void MessageClient::impl::set_server (QString const& server_name, QStringList const& network_interface_names) { server_.setAddress (server_name); - network_interface_ = QNetworkInterface::interfaceFromName (network_interface_name); + network_interfaces_.clear (); + for (auto const& net_if_name : network_interface_names) + { + network_interfaces_.push_back (QNetworkInterface::interfaceFromName (net_if_name)); + } + if (server_.isNull () && server_name.size ()) // DNS lookup required { // queue a host address lookup @@ -162,33 +167,10 @@ void MessageClient::impl::start () return; } - TRACE_UDP ("Trying server:" << server_.toString () << "on interface:" << network_interface_.humanReadableName ()); - QHostAddress interface_ip {QHostAddress::Any}; - if (network_interface_.isValid ()) - { - if (is_multicast_address (server_) && !(network_interface_.flags () & QNetworkInterface::CanMulticast)) - { - Q_EMIT self_->error ("Network interface is not multicast capable, please try another"); - return; - } - for (auto const& ae : network_interface_.addressEntries ()) - { - auto const& ip = ae.ip (); - if (server_.protocol () == ip.protocol ()) - { - interface_ip = ip; - break; - } - } - if (QHostAddress {QHostAddress::Any} == interface_ip) - { - Q_EMIT self_->error ("Network interface has no suitable address for server IP protocol, please try another"); - pending_messages_.clear (); // discard - return; - } - } + TRACE_UDP ("Trying server:" << server_.toString ()); + QHostAddress interface_addr {IPv6Protocol == server_.protocol () ? QHostAddress::AnyIPv6 : QHostAddress::AnyIPv4}; - if (localAddress () != interface_ip) + if (localAddress () != interface_addr) { if (UnconnectedState != state () || state ()) { @@ -196,8 +178,8 @@ void MessageClient::impl::start () } // bind to an ephemeral port on the selected interface and set // up for sending datagrams - bind (interface_ip); - setMulticastInterface (network_interface_); + bind (interface_addr); + qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress (); // set multicast TTL to limit scope when sending to multicast // group addresses @@ -210,7 +192,7 @@ void MessageClient::impl::start () // clear any backlog while (pending_messages_.size ()) { - send_message (pending_messages_.dequeue ()); + send_message (pending_messages_.dequeue (), false); } } @@ -438,14 +420,11 @@ void MessageClient::impl::heartbeat () if (server_port_ && !server_.isNull ()) { QByteArray message; - NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_, schema_}; - hb << NetworkMessage::Builder::schema_number // maximum schema number accepted - << version_.toUtf8 () << revision_.toUtf8 (); - if (OK == check_status (hb)) - { - TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_); - writeDatagram (message, server_, server_port_); - } + NetworkMessage::Builder out {&message, NetworkMessage::Heartbeat, id_, schema_}; + out << NetworkMessage::Builder::schema_number // maximum schema number accepted + << version_.toUtf8 () << revision_.toUtf8 (); + TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_); + send_message (out, message, false); } } @@ -455,15 +434,12 @@ void MessageClient::impl::closedown () { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Close, id_, schema_}; - if (OK == check_status (out)) - { - TRACE_UDP (""); - writeDatagram (message, server_, server_port_); - } + TRACE_UDP (""); + send_message (out, message, false); } } -void MessageClient::impl::send_message (QByteArray const& message) +void MessageClient::impl::send_message (QByteArray const& message, bool queue_if_pending) { if (server_port_) { @@ -471,11 +447,15 @@ void MessageClient::impl::send_message (QByteArray const& message) { if (message != last_message_) // avoid duplicates { - writeDatagram (message, server_, server_port_); + for (auto const& net_if : network_interfaces_) + { + setMulticastInterface (net_if); + writeDatagram (message, server_, server_port_); + } last_message_ = message; } } - else + else if (queue_if_pending) { pending_messages_.enqueue (message); } @@ -509,7 +489,7 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision, QString const& server_name, port_type server_port, - QString const& network_interface_name, + QStringList const& network_interface_names, int TTL, QObject * self) : QObject {self} , m_ {id, version, revision, server_port, TTL, this} @@ -532,7 +512,7 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString Q_EMIT error (m_->errorString ()); } }); - m_->set_server (server_name, network_interface_name); + m_->set_server (server_name, network_interface_names); } QHostAddress MessageClient::server_address () const @@ -545,9 +525,9 @@ auto MessageClient::server_port () const -> port_type return m_->server_port_; } -void MessageClient::set_server (QString const& server_name, QString const& network_interface_name) +void MessageClient::set_server (QString const& server_name, QStringList const& network_interface_names) { - m_->set_server (server_name, network_interface_name); + m_->set_server (server_name, network_interface_names); } void MessageClient::set_server_port (port_type server_port) diff --git a/Network/MessageClient.hpp b/Network/MessageClient.hpp index d0066dbe4..cc348be2d 100644 --- a/Network/MessageClient.hpp +++ b/Network/MessageClient.hpp @@ -36,7 +36,7 @@ public: // messages will be silently dropped until a server host lookup is complete MessageClient (QString const& id, QString const& version, QString const& revision, QString const& server_name, port_type server_port, - QString const& network_interface_name, + QStringList const& network_interface_names, int TTL, QObject * parent = nullptr); // query server details @@ -46,7 +46,7 @@ public: // initiate a new server host lookup or if the server name is empty // the sending of messages is disabled, if an interface is specified // then that interface is used for outgoing datagrams - Q_SLOT void set_server (QString const& server_name, QString const& network_interface_name); + Q_SLOT void set_server (QString const& server_name, QStringList const& network_interface_names); // change the server port messages are sent to Q_SLOT void set_server_port (port_type server_port = 0u); diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index d110bfc44..a0fe90c47 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -266,17 +266,17 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () void MessageAggregatorMainWindow::restart_server () { QSet net_ifs; - if (network_interfaces_combo_box_->isVisible ()) - { - auto model = static_cast (network_interfaces_combo_box_->model ()); - for (int row = 0; row < model->rowCount (); ++row) - { - if (Qt::Checked == model->item (row)->checkState ()) - { - net_ifs << model->item (row)->data ().toString (); - } - } - } + if (network_interfaces_combo_box_->isVisible ()) + { + auto model = static_cast (network_interfaces_combo_box_->model ()); + for (int row = 0; row < model->rowCount (); ++row) + { + if (Qt::Checked == model->item (row)->checkState ()) + { + net_ifs << model->item (row)->data ().toString (); + } + } + } server_->start (port_spin_box_->value () , QHostAddress {multicast_group_line_edit_->text ()} , net_ifs); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 78d1a0c52..2d028f074 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -65,14 +65,14 @@ public: { if (f != dial_frequency_) { - std::cout << tr ("%1(%2): Dial frequency changed to %3") - .arg (key_.second).arg (key_.first.toString ()).arg (f).toStdString () << std::endl; + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Dial frequency changed to %1"}.arg (f).toStdString () << std::endl; dial_frequency_ = f; } if (mode + sub_mode != mode_) { - std::cout << tr ("%1(%2): Mode changed to %3") - .arg (key_.second).arg (key_.first.toString ()).arg (mode + sub_mode).toStdString () << std::endl; + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Mode changed to %1"}.arg (mode + sub_mode).toStdString () << std::endl; mode_ = mode + sub_mode; } } @@ -88,8 +88,8 @@ public: << "Dt:" << delta_time << "Df:" << delta_frequency << "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high") << "On air:" << !off_air; - std::cout << tr ("%1(%2): Decoded %3") - .arg (key_.second).arg (key_.first.toString ()).arg (message).toStdString () << std::endl; + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Decoded %1"}.arg (message).toStdString () << std::endl; } } @@ -102,8 +102,9 @@ public: qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "drift:" << drift; - std::cout << tr ("%1(%2): WSPR decode %3 grid %4 power: %5") - .arg (key_.second).arg (key_.first.toString ()).arg (callsign).arg (grid).arg (power).toStdString () + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"WSPR decode %1 grid %2 power: %3"} + .arg (callsign).arg (grid).arg (power).toStdString () << "On air:" << !off_air << std::endl; } } @@ -125,12 +126,13 @@ public: << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent << "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode; std::cout << QByteArray {80, '-'}.data () << '\n'; - std::cout << tr ("%1(%2): Logged %3 grid: %4 power: %5 sent: %6 recd: %7 freq: %8 time_off: %9 op: %10 my_call: %11 my_grid: %12 exchange_sent: %13 exchange_rcvd: %14 comments: %15 prop_mode: %16") - .arg (key_.second).arg (key.first.toString ()).arg (dx_call).arg (dx_grid).arg (tx_power) - .arg (report_sent).arg (report_received) - .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) - .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) - .arg (comments).arg (prop_mode).toStdString () + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Logged %1 grid: %2 power: %3 sent: %4 recd: %5 freq: %6 time_off: %7 op: %8 my_call: %9 my_grid: %10 exchange_sent: %11 exchange_rcvd: %12 comments: %13 prop_mode: %14"} + .arg (dx_call).arg (dx_grid).arg (tx_power) + .arg (report_sent).arg (report_received) + .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) + .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) + .arg (comments).arg (prop_mode).toStdString () << std::endl; } } diff --git a/widgets/CheckableItemComboBox.cpp b/widgets/CheckableItemComboBox.cpp index 3ef926243..13115c993 100644 --- a/widgets/CheckableItemComboBox.cpp +++ b/widgets/CheckableItemComboBox.cpp @@ -25,7 +25,7 @@ public: }; CheckableItemComboBox::CheckableItemComboBox (QWidget * parent) - : QComboBox {parent} + : LazyFillComboBox {parent} , model_ {new QStandardItemModel()} { setModel (model_.data ()); diff --git a/widgets/CheckableItemComboBox.hpp b/widgets/CheckableItemComboBox.hpp index 2aa3e9831..21e751167 100644 --- a/widgets/CheckableItemComboBox.hpp +++ b/widgets/CheckableItemComboBox.hpp @@ -1,9 +1,10 @@ #ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__ #define CHECKABLE_ITEM_COMBO_BOX_HPP__ -#include #include +#include "LazyFillComboBox.hpp" + class QStandardItemModel; class QStandardItem; @@ -12,7 +13,7 @@ class QStandardItem; * http://stackoverflow.com/questions/8422760/combobox-of-checkboxes */ class CheckableItemComboBox - : public QComboBox + : public LazyFillComboBox { Q_OBJECT diff --git a/widgets/LazyFillComboBox.hpp b/widgets/LazyFillComboBox.hpp index 37af60f0b..7ac828fed 100644 --- a/widgets/LazyFillComboBox.hpp +++ b/widgets/LazyFillComboBox.hpp @@ -10,7 +10,7 @@ class QWidget; // // QComboBox derivative that signals show and hide of the pop up list. // -class LazyFillComboBox final +class LazyFillComboBox : public QComboBox { Q_OBJECT diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 6fb8e1a5a..89117ecd9 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -414,7 +414,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_messageClient {new MessageClient {QApplication::applicationName (), version (), revision (), m_config.udp_server_name (), m_config.udp_server_port (), - m_config.udp_interface_name (), m_config.udp_TTL (), + m_config.udp_interface_names (), m_config.udp_TTL (), this}}, m_psk_Reporter {&m_config, QString {"WSJT-X v" + version () + " " + m_revision}.simplified ()}, m_manual {&m_network_manager}, @@ -7826,7 +7826,7 @@ void MainWindow::networkError (QString const& e) , MessageBox::Cancel)) { // retry server lookup - m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_name ()); + m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_names ()); } } From c15f244a091366100cc8e294bdefb9c943a2273c Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 5 Nov 2020 11:30:48 +0000 Subject: [PATCH 41/73] Comment out diagnostic prints --- Configuration.cpp | 4 ++-- Network/MessageClient.cpp | 2 +- UDPExamples/MessageServer.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 7f68bb417..a13dc2723 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -2418,7 +2418,7 @@ void Configuration::impl::on_udp_server_line_edit_editingFinished () if (server.size () && ha.isNull ()) { // queue a host address lookup - qDebug () << "server host DNS lookup:" << server; + // qDebug () << "server host DNS lookup:" << server; #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) dns_lookup_id_ = QHostInfo::lookupHost (server, this, &Configuration::impl::host_info_results); #else @@ -2443,7 +2443,7 @@ void Configuration::impl::host_info_results (QHostInfo host_info) else { auto const& server_addresses = host_info.addresses (); - qDebug () << "message server addresses:" << server_addresses; + // qDebug () << "message server addresses:" << server_addresses; if (server_addresses.size ()) { check_multicast (server_addresses[0]); diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 2e721d5f7..5ac6a41c1 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -179,7 +179,7 @@ void MessageClient::impl::start () // bind to an ephemeral port on the selected interface and set // up for sending datagrams bind (interface_addr); - qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress (); + // qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress (); // set multicast TTL to limit scope when sending to multicast // group addresses diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 6745fe0a7..8aadd08a6 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -434,7 +434,7 @@ MessageServer::MessageServer (QObject * parent, QString const& version, QString void MessageServer::start (port_type port, QHostAddress const& multicast_group_address , QSet const& network_interface_names) { - qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names; + // qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names; if (port != m_->localPort () || multicast_group_address != m_->multicast_group_address_ || network_interface_names != m_->network_interfaces_) From 9434c447cd0ab329fdbfe32e1a2c879e65f7c42b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 00:33:53 +0000 Subject: [PATCH 42/73] Ensure multicast UDP is sent to at least the loop-back interface Also send multicast UDP to every selected network interface. --- Configuration.cpp | 44 ++++++++++++++++++++++++++++++++++----- Configuration.ui | 11 ++++++++-- Network/MessageClient.cpp | 15 +++++++++++-- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index a13dc2723..7bd94b5d4 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -443,7 +443,8 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); - void load_network_interfaces (CheckableItemComboBox *, QStringList const& current); + void load_network_interfaces (CheckableItemComboBox *, QStringList current); + void validate_network_interfaces (CheckableItemComboBox *); QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -656,6 +657,7 @@ private: int dns_lookup_id_; port_type udp_server_port_; QStringList udp_interface_names_; + QString loopback_interface_name_; int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; @@ -1085,6 +1087,9 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); + connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, [this] (QString const& /*text*/) { + validate_network_interfaces (ui_->udp_interfaces_combo_box); + }); // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { @@ -2995,7 +3000,7 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com } // load the available network interfaces into the selection combo box -void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList const& current) +void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList current) { combo_box->clear (); for (auto const& net_if : QNetworkInterface::allInterfaces ()) @@ -3003,11 +3008,13 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo auto flags = QNetworkInterface::IsUp | QNetworkInterface::CanMulticast; if ((net_if.flags () & flags) == flags) { - auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + loopback_interface_name_ = net_if.name (); + } auto item = combo_box->addCheckItem (net_if.humanReadableName () , net_if.name () - , is_loopback || current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); - item->setEnabled (!is_loopback); + , current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); auto hw_addr = net_if.hardwareAddress (); @@ -3029,6 +3036,33 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo } } +// get the select network interfaces from the selection combo box +void Configuration::impl::validate_network_interfaces (CheckableItemComboBox * combo_box) +{ + auto model = static_cast (combo_box->model ()); + bool has_checked {false}; + int loopback_row {-1}; + for (int row = 0; row < model->rowCount (); ++row) + { + if (model->item (row)->data ().toString () == loopback_interface_name_) + { + loopback_row = row; + } + else if (Qt::Checked == model->item (row)->checkState ()) + { + has_checked = true; + } + } + if (loopback_row >= 0) + { + if (!has_checked) + { + model->item (loopback_row)->setCheckState (Qt::Checked); + } + model->item (loopback_row)->setEnabled (has_checked); + } +} + // get the select network interfaces from the selection combo box QStringList Configuration::impl::get_selected_network_interfaces (CheckableItemComboBox * combo_box) { diff --git a/Configuration.ui b/Configuration.ui index 1b6ef8926..17fd1a326 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -1885,7 +1885,7 @@ and DX Grid fields when a 73 or free text message is sent. - <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be broadcast.</p></body></html> + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> 65534 @@ -1903,10 +1903,17 @@ and DX Grid fields when a 73 or free text message is sent. - + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + 255 diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 5ac6a41c1..3cf00ee3b 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -103,6 +103,7 @@ public: void MessageClient::impl::set_server (QString const& server_name, QStringList const& network_interface_names) { + // qDebug () << "MessageClient server:" << server_name << "port:" << server_port_ << "interfaces:" << network_interface_names; server_.setAddress (server_name); network_interfaces_.clear (); for (auto const& net_if_name : network_interface_names) @@ -447,9 +448,19 @@ void MessageClient::impl::send_message (QByteArray const& message, bool queue_if { if (message != last_message_) // avoid duplicates { - for (auto const& net_if : network_interfaces_) + if (is_multicast_address (server_)) { - setMulticastInterface (net_if); + // send datagram on each selected network interface + std::for_each (network_interfaces_.begin (), network_interfaces_.end () + , [&] (QNetworkInterface const& net_if) { + setMulticastInterface (net_if); + // qDebug () << "Multicast UDP datagram sent to:" << server_ << "port:" << server_port_ << "on:" << multicastInterface ().humanReadableName (); + writeDatagram (message, server_, server_port_); + }); + } + else + { + // qDebug () << "Unicast UDP datagram sent to:" << server_ << "port:" << server_port_; writeDatagram (message, server_, server_port_); } last_message_ = message; From d953c455fe05bb5326695b228cd46168979256b0 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 01:27:36 +0000 Subject: [PATCH 43/73] Ensure network interfaces validation is run on start up --- Configuration.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 7bd94b5d4..4674087b0 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -444,7 +444,7 @@ private: void update_audio_channels (QComboBox const *, int, QComboBox *, bool); void load_network_interfaces (CheckableItemComboBox *, QStringList current); - void validate_network_interfaces (CheckableItemComboBox *); + Q_SLOT void validate_network_interfaces (QString const&); QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -1087,9 +1087,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); - connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, [this] (QString const& /*text*/) { - validate_network_interfaces (ui_->udp_interfaces_combo_box); - }); + connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, this, &Configuration::impl::validate_network_interfaces); // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { @@ -3037,9 +3035,9 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo } // get the select network interfaces from the selection combo box -void Configuration::impl::validate_network_interfaces (CheckableItemComboBox * combo_box) +void Configuration::impl::validate_network_interfaces (QString const& /*text*/) { - auto model = static_cast (combo_box->model ()); + auto model = static_cast (ui_->udp_interfaces_combo_box->model ()); bool has_checked {false}; int loopback_row {-1}; for (int row = 0; row < model->rowCount (); ++row) From 499704d27530faa0f11b7f3759e5dc1840612338 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 01:28:19 +0000 Subject: [PATCH 44/73] Allow message_aggregator example to not join on he loopback interface --- UDPExamples/MessageAggregatorMainWindow.cpp | 41 ++++++++++++++++++--- UDPExamples/MessageAggregatorMainWindow.hpp | 2 + 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index a0fe90c47..63b1e45b5 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -107,13 +107,16 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () auto flags = QNetworkInterface::IsRunning | QNetworkInterface::CanMulticast; if ((net_if.flags () & flags) == flags) { - auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + loopback_interface_name_ = net_if.name (); + } auto item = network_interfaces_combo_box_->addCheckItem (net_if.humanReadableName () , net_if.name () - , is_loopback ? Qt::Checked : Qt::Unchecked); - item->setEnabled (!is_loopback); - auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) - .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); + , Qt::Unchecked); + auto tip = QString {"name(index): %1(%2) - %3"} + .arg (net_if.name ()).arg (net_if.index ()) + .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); auto hw_addr = net_if.hardwareAddress (); if (hw_addr.size ()) { @@ -131,6 +134,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () item->setToolTip (tip); } } + connect (network_interfaces_combo_box_, &QComboBox::currentTextChanged, this, &MessageAggregatorMainWindow::validate_network_interfaces); + validate_network_interfaces (QString {}); log_table_view_->setModel (log_); log_table_view_->verticalHeader ()->hide (); @@ -369,4 +374,30 @@ void MessageAggregatorMainWindow::change_highlighting (QString const& call, QCol } } +void MessageAggregatorMainWindow::validate_network_interfaces (QString const& /*text*/) +{ + auto model = static_cast (network_interfaces_combo_box_->model ()); + bool has_checked {false}; + int loopback_row {-1}; + for (int row = 0; row < model->rowCount (); ++row) + { + if (model->item (row)->data ().toString () == loopback_interface_name_) + { + loopback_row = row; + } + else if (Qt::Checked == model->item (row)->checkState ()) + { + has_checked = true; + } + } + if (loopback_row >= 0) + { + if (!has_checked) + { + model->item (loopback_row)->setCheckState (Qt::Checked); + } + model->item (loopback_row)->setEnabled (has_checked); + } +} + #include "moc_MessageAggregatorMainWindow.cpp" diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 1bff0d692..71ab89ffe 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -46,6 +46,7 @@ private: void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, bool last_only = false); + Q_SLOT void validate_network_interfaces (QString const&); // maps client id to widgets using ClientsDictionary = QHash; @@ -59,6 +60,7 @@ private: QSpinBox * port_spin_box_; QLineEdit * multicast_group_line_edit_; CheckableItemComboBox * network_interfaces_combo_box_; + QString loopback_interface_name_; QLabel * network_interfaces_form_label_widget_; QTableView * log_table_view_; QListWidget * calls_of_interest_; From e0888eb70c430a11671bef13bd82ad867c190434 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Fri, 6 Nov 2020 09:33:44 -0600 Subject: [PATCH 45/73] Restore wsprsimf and dependencies. --- lib/wsprd/wspr_params.f90 | 20 +++++++ lib/wsprd/wspr_wav.f90 | 49 +++++++++++++++++ lib/wsprd/wsprsimf.f90 | 113 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 lib/wsprd/wspr_params.f90 create mode 100644 lib/wsprd/wspr_wav.f90 create mode 100644 lib/wsprd/wsprsimf.f90 diff --git a/lib/wsprd/wspr_params.f90 b/lib/wsprd/wspr_params.f90 new file mode 100644 index 000000000..ebfc4cf74 --- /dev/null +++ b/lib/wsprd/wspr_params.f90 @@ -0,0 +1,20 @@ +parameter (NN=162) +parameter (NSPS0=8192) !Samples per symbol at 12000 S/s +parameter (NDOWN=32) +parameter (NSPS=NSPS0/NDOWN) +parameter (NZ=NSPS*NN) !Samples in waveform at 12000 S/s +parameter (NZ0=NSPS0*NN) !Samples in waveform at 375 S/s +parameter (NMAX=120*12000) !Samples in waveform at 375 S/s + +! Define the sync vector: +integer*1 sync(162) +data sync/ & + 1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0, & + 0,1,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1, & + 0,0,0,0,0,0,1,0,1,1,0,0,1,1,0,1,0,0,0,1, & + 1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1, & + 0,0,1,0,1,1,0,0,0,1,1,0,1,0,1,0,0,0,1,0, & + 0,0,0,0,1,0,0,1,0,0,1,1,1,0,1,1,0,0,1,1, & + 0,1,0,0,0,1,1,1,0,0,0,0,0,1,0,1,0,0,1,1, & + 0,0,0,0,0,0,0,1,1,0,1,0,1,1,0,0,0,1,1,0, & + 0,0/ diff --git a/lib/wsprd/wspr_wav.f90 b/lib/wsprd/wspr_wav.f90 new file mode 100644 index 000000000..99ba70c5d --- /dev/null +++ b/lib/wsprd/wspr_wav.f90 @@ -0,0 +1,49 @@ +subroutine wspr_wav(baud,xdt,h,f0,itone,snrdb,iwave) + +! Generate iwave() from itone(). + + include 'wspr_params.f90' + integer itone(NN) + integer*2 iwave(NMAX) + real*8 twopi,dt,dphi0,dphi1,dphi,phi + real dat(NMAX) + + twopi=8.d0*atan(1.d0) + dt=1.d0/12000.d0 + baud=375.0/256.0 + + dat=0. + if(snrdb.lt.90) then + do i=1,NMAX + dat(i)=gran() !Generate gaussian noise + enddo + bandwidth_ratio=2500.0/6000.0 + sig=sqrt(2*bandwidth_ratio)*10.0**(0.05*snrdb) + else + sig=1.0 + endif + + phi=0.d0 + k=nint(xdt/dt) + do j=1,NN + dphi=twopi*(f0+h*(itone(j)-1.5)*baud)*dt + do i=1,NSPS0 + k=k+1 + phi=mod(phi+dphi,twopi) + if(k.gt.0 .and. k.le.NMAX) dat(k)=dat(k) + sig*sin(phi) + enddo + enddo + + rms=100.0 + if(snrdb.lt.90.0) then + dat=rms*dat; + if(maxval(abs(dat)).gt.32767.0) print*,"Warning - data will be clipped." + else + datpk=maxval(abs(dat)) + fac=32767.9/datpk + dat=fac*dat + endif + iwave=nint(dat) + + return +end subroutine wspr_wav diff --git a/lib/wsprd/wsprsimf.f90 b/lib/wsprd/wsprsimf.f90 new file mode 100644 index 000000000..d6ee25d44 --- /dev/null +++ b/lib/wsprd/wsprsimf.f90 @@ -0,0 +1,113 @@ +!------------------------------------------------------------------------------- +! +! This file is part of the WSPR application, Weak Signal Propagation Reporter +! +!------------------------------------------------------------------------------- + +program wsprsim + + use wavhdr + include 'wspr_params.f90' + type(hdr) hwav + character arg*12,fname14*14,fname15*15 + character*22 msg,msgsent + complex c0(0:NMAX/NDOWN-1) + complex c(0:NMAX/NDOWN-1) + integer itone(NN) + integer*2 iwave(NMAX) + real*8 fMHz + +! Get command-line argument(s) + nargs=iargc() + if(nargs.ne.8) then + print*,'Usage: wsprsim "message" f0 DT fsp del nwav nfiles snr' + print*,'Example: wsprsim "K1ABC FN42 30" 50 0.0 0.1 1.0 1 10 -33' + go to 999 + endif + call getarg(1,msg) !Message to be transmitted + call getarg(2,arg) + read(arg,*) f0 !Freq relative to WSPR-band center (Hz) + call getarg(3,arg) + read(arg,*) xdt !Time offset from nominal (s) + call getarg(4,arg) + read(arg,*) fspread !Watterson frequency spread (Hz) + call getarg(5,arg) + read(arg,*) delay !Watterson delay (ms) + call getarg(6,arg) + read(arg,*) nwav !1 for *.wav file, 0 for *.c2 file + call getarg(7,arg) + read(arg,*) nfiles !Number of files + call getarg(8,arg) + read(arg,*) snrdb !SNR_2500 + + twopi=8.0*atan(1.0) + fs=12000.0/NDOWN + dt=1.0/fs + tt=NSPS*dt + baud=12000.0/8192.0 + + txt=NZ*dt !Transmission length (s) + bandwidth_ratio=2500.0/(fs/2.0) + sig=sqrt(bandwidth_ratio) * 10.0**(0.05*snrdb) + if(snrdb.gt.90.0) sig=1.0 + txt=NN*NSPS0/12000.0 + + call genwspr(msg,msgsent,itone) !Encode the message, get itone + + write(*,1000) f0,xdt,txt,snrdb,fspread,delay,nfiles,msgsent +1000 format('f0:',f9.3,' DT:',f6.2,' txt:',f6.1,' SNR:',f6.1, & + ' fspread:',f6.1,' delay:',f6.1,' nfiles:',i3,2x,a22) +! write(*,*) "Channel symbols: " +! write(*,'(162i2)') itone + + h=1.0 + phi=0.0 + c0=0. + k=-1 + nint(xdt/dt) + do j=1,NN + dphi=-twopi*(f0+h*(itone(j)-1.5)*baud)*dt + do i=1,NSPS + k=k+1 + phi=mod(phi+dphi,twopi) + if(k.ge.0 .and. k.lt.NMAX/NDOWN) c0(k)=cmplx(cos(phi),sin(phi)) + enddo + enddo + call sgran() + do ifile=1,nfiles + c=c0 + if(nwav.eq.0) then + if( fspread .ne. 0.0 .or. delay .ne. 0.0 ) then + call watterson(c,NMAX/NDOWN,NN*NSPS,fs,delay,fspread) + endif + c=c*sig + if(snrdb.lt.90) then + do i=0,NMAX/NDOWN-1 !Add gaussian noise at specified SNR + xnoise=gran() + ynoise=gran() + c(i)=c(i) + cmplx(xnoise,ynoise) + enddo + endif + write(fname14,1100) ifile +1100 format('000000_',i4.4,'.c2') + open(10,file=fname14,status='unknown',access='stream') + fMHz=10.1387d0 + nmin=2 + write(10) fname14,nmin,fMHz,c !Save to *.c2 file + close(10) + write(*,1108) ifile,xdt,f0,snrdb,fname14 +1108 format(i4,f7.2,f8.2,f7.1,2x,a14) + else + freq=1500.0+f0 + call wspr_wav(baud,xdt,h,freq,itone,snrdb,iwave) + hwav=default_header(12000,NMAX) + write(fname15,1102) ifile +1102 format('000000_',i4.4,'.wav') + open(10,file=fname15,status='unknown',access='stream') + write(10) hwav,iwave !Save to *.wav file + close(10) + write(*,1110) ifile,xdt,f0,snrdb,fname15 +1110 format(i4,f7.2,f8.2,f7.1,2x,a15) + endif + enddo + +999 end program wsprsim From ab780a324a571549cb9e299949696ad6b254ca8d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 18:28:59 +0000 Subject: [PATCH 46/73] Testing options Two new environment variables to control special testing behaviour: * WSJT_TX_BOTH - set to "1" to force transmission on both periods. * WSJT_REVERSE_DOPPLER - set to "1" to transpose Tx and Rx Doppler corrections. Use this to test Doppler tracking on a terrestrial link. --- main.cpp | 5 ++++- widgets/astro.h | 10 ++++++++++ widgets/mainwindow.cpp | 25 ++++++++++++++++++++----- widgets/mainwindow.h | 5 ++++- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/main.cpp b/main.cpp index 4c30f615c..dec9ba7de 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,8 @@ int main(int argc, char *argv[]) // Multiple instances communicate with jt9 via this QSharedMemory mem_jt9; + auto const env = QProcessEnvironment::systemEnvironment (); + QApplication a(argc, argv); try { @@ -411,7 +414,7 @@ int main(int argc, char *argv[]) } // run the application UI - MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash); + MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash, env); w.show(); splash.raise (); QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit())); diff --git a/widgets/astro.h b/widgets/astro.h index a2474072f..2b544872c 100644 --- a/widgets/astro.h +++ b/widgets/astro.h @@ -2,6 +2,8 @@ #ifndef ASTRO_H #define ASTRO_H +#include + #include #include @@ -34,9 +36,17 @@ public: Correction (Correction const&) = default; Correction& operator = (Correction const&) = default; + // testing facility used to test Doppler corrections on + // terrestrial links + void reverse () + { + std::swap (rx, tx); + } + FrequencyDelta rx; FrequencyDelta tx; }; + Correction astroUpdate(QDateTime const& t, QString const& mygrid, QString const& hisgrid, diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index d20331bc4..a7eb780da 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -233,8 +234,9 @@ namespace MainWindow::MainWindow(QDir const& temp_directory, bool multiple, MultiSettings * multi_settings, QSharedMemory *shdmem, unsigned downSampleFactor, - QSplashScreen * splash, QWidget *parent) : + QSplashScreen * splash, QProcessEnvironment const& env, QWidget *parent) : QMainWindow(parent), + m_env {env}, m_network_manager {this}, m_valid {true}, m_splash {splash}, @@ -266,6 +268,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_secBandChanged {0}, m_freqNominal {0}, m_freqTxNominal {0}, + m_reverse_Doppler {"1" == env.value ("WSJT_REVERSE_DOPPLER", "0")}, m_s6 {0.}, m_tRemaining {0.}, m_TRperiod {60.0}, @@ -926,9 +929,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, , "-a", QDir::toNativeSeparators (m_config.writeable_data_dir ().absolutePath ()) , "-t", QDir::toNativeSeparators (m_config.temp_dir ().absolutePath ()) }; - QProcessEnvironment env {QProcessEnvironment::systemEnvironment ()}; - env.insert ("OMP_STACKSIZE", "4M"); - proc_jt9.setProcessEnvironment (env); + QProcessEnvironment new_env {m_env}; + new_env.insert ("OMP_STACKSIZE", "4M"); + proc_jt9.setProcessEnvironment (new_env); proc_jt9.start(QDir::toNativeSeparators (m_appDir) + QDir::separator () + "jt9", jt9_args, QIODevice::ReadWrite | QIODevice::Unbuffered); @@ -4227,7 +4230,15 @@ void MainWindow::guiUpdate() transmitDisplay (true); statusUpdate (); } - if(!m_btxok && m_btxok0 && g_iptt==1) stopTx(); + if(!m_btxok && m_btxok0 && g_iptt==1) + { + stopTx(); + if ("1" == m_env.value ("WSJT_TX_BOTH", "0")) + { + m_txFirst = !m_txFirst; + ui->txFirstCheckBox->setChecked (m_txFirst); + } + } if(m_startAnother) { if(m_mode=="MSK144") { @@ -8193,6 +8204,10 @@ void MainWindow::astroUpdate () correction.tx = correction.tx / 10 * 10; } m_astroCorrection = correction; + if (m_reverse_Doppler) + { + m_astroCorrection.reverse (); + } } else { diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index 7a8537d03..272664e78 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -63,6 +63,7 @@ namespace Ui { class MainWindow; } +class QProcessEnvironment; class QSharedMemory; class QSplashScreen; class QSettings; @@ -103,7 +104,7 @@ public: explicit MainWindow(QDir const& temp_directory, bool multiple, MultiSettings *, QSharedMemory *shdmem, unsigned downSampleFactor, - QSplashScreen *, + QSplashScreen *, QProcessEnvironment const&, QWidget *parent = nullptr); ~MainWindow(); @@ -356,6 +357,7 @@ private: void setColorHighlighting(); void chkFT4(); + QProcessEnvironment const& m_env; NetworkAccessManager m_network_manager; bool m_valid; QSplashScreen * m_splash; @@ -407,6 +409,7 @@ private: Frequency m_freqNominal; Frequency m_freqTxNominal; Astro::Correction m_astroCorrection; + bool m_reverse_Doppler; double m_s6; double m_tRemaining; From 68056ae8fafab320b74b24ce80347b855f239ce4 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 18:28:59 +0000 Subject: [PATCH 47/73] Testing options Two new environment variables to control special testing behaviour: * WSJT_TX_BOTH - set to "1" to force transmission on both periods. * WSJT_REVERSE_DOPPLER - set to "1" to transpose Tx and Rx Doppler corrections. Use this to test Doppler tracking on a terrestrial link. --- main.cpp | 5 ++++- widgets/astro.h | 10 ++++++++++ widgets/mainwindow.cpp | 25 ++++++++++++++++++++----- widgets/mainwindow.h | 5 ++++- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/main.cpp b/main.cpp index 4c30f615c..dec9ba7de 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,8 @@ int main(int argc, char *argv[]) // Multiple instances communicate with jt9 via this QSharedMemory mem_jt9; + auto const env = QProcessEnvironment::systemEnvironment (); + QApplication a(argc, argv); try { @@ -411,7 +414,7 @@ int main(int argc, char *argv[]) } // run the application UI - MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash); + MainWindow w(temp_dir, multiple, &multi_settings, &mem_jt9, downSampleFactor, &splash, env); w.show(); splash.raise (); QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit())); diff --git a/widgets/astro.h b/widgets/astro.h index a2474072f..2b544872c 100644 --- a/widgets/astro.h +++ b/widgets/astro.h @@ -2,6 +2,8 @@ #ifndef ASTRO_H #define ASTRO_H +#include + #include #include @@ -34,9 +36,17 @@ public: Correction (Correction const&) = default; Correction& operator = (Correction const&) = default; + // testing facility used to test Doppler corrections on + // terrestrial links + void reverse () + { + std::swap (rx, tx); + } + FrequencyDelta rx; FrequencyDelta tx; }; + Correction astroUpdate(QDateTime const& t, QString const& mygrid, QString const& hisgrid, diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 64f7f4ec4..be5062fa0 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -233,8 +234,9 @@ namespace MainWindow::MainWindow(QDir const& temp_directory, bool multiple, MultiSettings * multi_settings, QSharedMemory *shdmem, unsigned downSampleFactor, - QSplashScreen * splash, QWidget *parent) : + QSplashScreen * splash, QProcessEnvironment const& env, QWidget *parent) : QMainWindow(parent), + m_env {env}, m_network_manager {this}, m_valid {true}, m_splash {splash}, @@ -266,6 +268,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_secBandChanged {0}, m_freqNominal {0}, m_freqTxNominal {0}, + m_reverse_Doppler {"1" == env.value ("WSJT_REVERSE_DOPPLER", "0")}, m_s6 {0.}, m_tRemaining {0.}, m_TRperiod {60.0}, @@ -926,9 +929,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, , "-a", QDir::toNativeSeparators (m_config.writeable_data_dir ().absolutePath ()) , "-t", QDir::toNativeSeparators (m_config.temp_dir ().absolutePath ()) }; - QProcessEnvironment env {QProcessEnvironment::systemEnvironment ()}; - env.insert ("OMP_STACKSIZE", "4M"); - proc_jt9.setProcessEnvironment (env); + QProcessEnvironment new_env {m_env}; + new_env.insert ("OMP_STACKSIZE", "4M"); + proc_jt9.setProcessEnvironment (new_env); proc_jt9.start(QDir::toNativeSeparators (m_appDir) + QDir::separator () + "jt9", jt9_args, QIODevice::ReadWrite | QIODevice::Unbuffered); @@ -4227,7 +4230,15 @@ void MainWindow::guiUpdate() transmitDisplay (true); statusUpdate (); } - if(!m_btxok && m_btxok0 && g_iptt==1) stopTx(); + if(!m_btxok && m_btxok0 && g_iptt==1) + { + stopTx(); + if ("1" == m_env.value ("WSJT_TX_BOTH", "0")) + { + m_txFirst = !m_txFirst; + ui->txFirstCheckBox->setChecked (m_txFirst); + } + } if(m_startAnother) { if(m_mode=="MSK144") { @@ -8193,6 +8204,10 @@ void MainWindow::astroUpdate () correction.tx = correction.tx / 10 * 10; } m_astroCorrection = correction; + if (m_reverse_Doppler) + { + m_astroCorrection.reverse (); + } } else { diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index 7a8537d03..272664e78 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -63,6 +63,7 @@ namespace Ui { class MainWindow; } +class QProcessEnvironment; class QSharedMemory; class QSplashScreen; class QSettings; @@ -103,7 +104,7 @@ public: explicit MainWindow(QDir const& temp_directory, bool multiple, MultiSettings *, QSharedMemory *shdmem, unsigned downSampleFactor, - QSplashScreen *, + QSplashScreen *, QProcessEnvironment const&, QWidget *parent = nullptr); ~MainWindow(); @@ -356,6 +357,7 @@ private: void setColorHighlighting(); void chkFT4(); + QProcessEnvironment const& m_env; NetworkAccessManager m_network_manager; bool m_valid; QSplashScreen * m_splash; @@ -407,6 +409,7 @@ private: Frequency m_freqNominal; Frequency m_freqTxNominal; Astro::Correction m_astroCorrection; + bool m_reverse_Doppler; double m_s6; double m_tRemaining; From 6a1223ce6f93dec8bb2c56f0a85c838a8cbcc1c3 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 7 Nov 2020 13:42:42 +0000 Subject: [PATCH 48/73] Updated Chinese and Hong Kong UI translations, tnx Sze-to, VR2UPU --- translations/wsjtx_zh.ts | 185 +++++++++++++++++++++++++----------- translations/wsjtx_zh_HK.ts | 174 +++++++++++++++++++++++---------- 2 files changed, 253 insertions(+), 106 deletions(-) diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index 05f8a773a..5a9824c8d 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -203,7 +203,7 @@ Freq(MHz) - 频率(MHz) + 频率(兆赫) @@ -807,22 +807,22 @@ Format: New CQ Zone - 新 CQ Zone + 新 CQ 区 New CQ Zone on Band - 新 CQ Zone 波段 + 新 CQ 区 波段 New ITU Zone - 新 ITU Zone + 新 ITU 区 New ITU Zone on Band - 新 ITU Zone 波段 + 新 ITU 区 波段 @@ -832,7 +832,7 @@ Format: f/g unset - 字體颜色未设置 + 字体颜色未设置 @@ -903,7 +903,7 @@ Format: URL Error - 网址出错误 + 网址错误 @@ -922,12 +922,12 @@ Format: JSON Error - JSON出错误 + JSON错误 Contents file syntax error %1 at character offset %2 - 内容文件语法出错误 %1 字符偏移量 %2 + 内容文件语法错误 %1 字符偏移量 %2 @@ -937,14 +937,14 @@ Format: File System Error - 文件系统出错误 + 文件系统错误 Failed to open "%1" Error: %2 - %3 未能打开 "%1" -出错误: %2 - %3 +错误: %2 - %3 @@ -974,7 +974,7 @@ Error: %2 - %3 Network Error - 网络出错误 + 网络错误 @@ -1083,7 +1083,7 @@ Error: %2 - %3 Freq (Hz) - 频率 (Hz) + 频率 (赫兹) @@ -1477,7 +1477,7 @@ Error: %2 - %3 Frequency (MHz) - 频率 (MHz) + 频率 (兆赫) @@ -1573,22 +1573,22 @@ Error: %2 - %3 Hamlib initialisation error - Hamlib 初始化出错误 + Hamlib 初始化错误 Hamlib settings file error: %1 at character offset %2 - Hamlib 设置文件出错误: %1 字符偏移量 %2 + Hamlib 设置文件错误: %1 字符偏移量 %2 Hamlib settings file error: top level must be a JSON object - Hamlib 设置文件出错误: 顶层必须是 JSON 对象 + Hamlib 设置文件错误: 顶层必须是 JSON 对象 Hamlib settings file error: config must be a JSON object - Hamlib 设置文件出错误: 配置必须是JSON对象 + Hamlib 设置文件错误: 配置必须是JSON对象 @@ -1598,7 +1598,7 @@ Error: %2 - %3 Hamlib error: %1 while %2 - Hamlib 出错误: %1 当 %2 + Hamlib 错误: %1 当 %2 @@ -2092,7 +2092,7 @@ Error(%2): %3 Log &QSO - 纪录通联(&Q) + 记录通联(&Q) @@ -2433,7 +2433,7 @@ Yellow when too low Select operating band or enter frequency in MHz or enter kHz increment followed by k. - 选择工作频段或输入 MHz 频率或输入 kHz 增量,然后输入 k. + 选择工作频段或输入兆赫频率或输入千赫增量, 然后输入 k. @@ -2489,7 +2489,7 @@ Yellow when too low Frequency tolerance (Hz) - 频率容差 (Hz) + 频率容差 (赫兹) @@ -2617,7 +2617,7 @@ Yellow when too low Frequency to call CQ on in kHz above the current MHz - 呼叫 CQ 的频率以 kHz 高于当前的 MHz + 呼叫 CQ 的频率以千赫高于当前的兆赫 @@ -2704,12 +2704,12 @@ When not checked you can view the calibration results. <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - <html><head/><body><p>信号报告: 参考2500 Hz 带宽 (dB) 中的信噪比.</p></body></html> + <html><head/><body><p>信号报告: 参考2500赫兹带宽 (分贝) 中的信噪比.</p></body></html> Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - 信号报告: 参考2500 Hz 带宽 (dB) 中的信噪比. + 信号报告: 参考2500赫兹带宽 (分贝) 中的信噪比. @@ -3282,7 +3282,7 @@ list. The list can be maintained in Settings (F2). About WSJT-X - 有关 WSJT-X + 关于 WSJT-X @@ -3342,7 +3342,7 @@ list. The list can be maintained in Settings (F2). Special mouse commands - 滑鼠特殊组合 + 特殊鼠标动作 @@ -3583,7 +3583,7 @@ list. The list can be maintained in Settings (F2). Color highlighting scheme - 颜色突显方案 + 颜色突出显示方案 @@ -3660,7 +3660,7 @@ list. The list can be maintained in Settings (F2). Enumerating audio devices - + 列举音频设备 @@ -3703,7 +3703,7 @@ list. The list can be maintained in Settings (F2). Error removing "%1" - 删除时出错误 "%1" + 删除时错误 "%1" @@ -3720,7 +3720,7 @@ list. The list can be maintained in Settings (F2). File Open Error - 文件打开出错误 + 文件打开错误 @@ -3861,7 +3861,7 @@ list. The list can be maintained in Settings (F2). Special Mouse Commands - 滑鼠特殊组合 + 特殊鼠标组合 @@ -3955,7 +3955,51 @@ list. The list can be maintained in Settings (F2). <tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr> </table> Keyboard shortcuts help window contents - + <table cellspacing=1> +<tr><td><b>Esc</b></td><td>停止发送, 中止通联, 清除下一个呼叫队列</td></tr> +<tr><td><b>F1</b></td><td>联机用户指南(Alt:transmitTx6)</td></tr> +<tr><td><b>Shift+F1</b></td><td>版权声明</td></tr> +<tr><td><b>Ctrl+F1</b></td><td>关于WSJT-X</td></tr> +<tr><td><b>F2</b></td><td>打开设置窗口(Alt:transmitTx2)</td></tr> +<tr><td><b>F3</b></td><td>显示键盘快捷键(Alt:transmitTx3)</td></tr> +<tr><td><b>F4</b></td><td>清除DX呼叫, DX网格, Tx消息1-4(Alt:发送Tx4)</td></tr> +<tr><td><b>Alt+F4</b></td><td>退出程序</td></tr> +<tr><td><b>F5</b></td><td>显示特殊鼠标命令(Alt:发送Tx5)</td></tr> +<tr><td><b>F6</b></td><td>打开目录中的下一个文件(Alt:toggle“Call1st”)</td></tr> +<tr><td><b>Shift+F6</b></td><td>在目录中解码所有剩余的文件</td></tr> +<tr><td><b>F7</b></td><td>显示消息平均窗口</td></tr> +<tr><td><b>F11</b></td><td>将接收频率下移1赫兹</td></tr> +<tr><td><b>Ctrl+F11</b></td><td>将相同的接收和发送频率下移1赫兹</td></tr> +<tr><td><b>Shift+F11</b></td><td>将发送频率下移60赫兹(FT8)或90赫兹(FT4)</td></tr> +<tr><td><b>Ctrl+Shift+F11</b></td><td>降低拨号频率2000赫兹</td></tr> +<tr><td><b>F12</b></td><td>将接收频率上移1赫兹</td></tr> +<tr><td><b>Ctrl+F12</b></td><td>将相同的接收和发送频率向上移动1赫兹</td></tr> +<tr><td><b>Shift+F12</b></td><td>将发送频率上移60赫兹(FT8)或90赫兹(FT4)</td></tr> +<tr><td><b>Ctrl+Shift+F12</b></td><td>将拨号频率向上移动2000赫兹</td></tr> +<tr><td><b>Alt+1-6</b></td><td>现在将变速器设置为表1上的此号码</td></tr> +<tr><td><b>Ctl+1-6</b></td><td>将下一次传输设置为选项卡1上的此号码</td></tr> +<tr><td><b>Alt+B</b></td><td>切换“最佳S+P”状态</td></tr> +<tr><td><b>Alt+C</b></td><td>切换“第一次呼叫”复选框</td></tr> +<tr><td><b>Alt+D</b></td><td>以通联频率再次解码</td></tr> +<tr><td><b>Shift+D</b></td><td>完全解码(两个窗口)</td></tr> +<tr><td><b>Ctrl+E</b></td><td>打开TXeven/1st</td></tr> +<tr><td><b>Shift+E</b></td><td>关闭TXeven/1st</td></tr> +<tr><td><b>Alt+E</b></td><td>擦除</td></tr> +<tr><td><b>Ctrl+F</b></td><td>编辑自定义文本信息框</td></tr> +<tr><td><b>Alt+G</b></td><td>生成标准消息</td></tr> +<tr><td><b>Alt+H</b></td><td>停止发送</td></tr> +<tr><td><b>Ctrl+L</b></td><td>在数据库中查找呼号, 生成标准消息</td></tr> +<tr><td><b>Alt+M</b></td><td>监听</td></tr> +<tr><td><b>Alt+N</b></td><td>启用发送</td></tr> +<tr><td><b>Ctrl+O</b></td><td>打开.wav文件</td></tr> +<tr><td><b>Alt+O</b></td><td>更换操作员</td></tr> +<tr><td><b>Alt+Q</b></td><td>记录通联</td></tr> +<tr><td><b>Ctrl+R</b></td><td>将Tx4信息设置为RRR(不在FT4中)</td></tr> +<tr><td><b>Alt+R</b></td><td>将Tx4信息设置为RR73</td></tr> +<tr><td><b>Alt+S</b></td><td>停止监听</td></tr> +<tr><td><b>Alt+T</b></td><td>切换调谐状态</td></tr> +<tr><td><b>Alt+Z</b></td><td>清除挂起解码器状态</td></tr> +</table> @@ -3991,7 +4035,36 @@ list. The list can be maintained in Settings (F2). </tr> </table> Mouse commands help window contents - + <table cellpadding=5> + <tr> + <th align="right">点击</th> + <th align="left">动作</th> + </tr> + <tr> + <td align="right">瀑布图:</td> + <td><b>单击 </b>设置接收频率。<br> + <b>按住Shift键单击 </b>可设置发送频率。<br> + <b>按住Ctrl键单击或右键单击 </b>可设置接收和发送频率。<br> + <b>双击</b> 可以在接收频率解码。<br/> + </td> + </tr> + <tr> + <td align="right">解码信息:</td> + <td><b>双击</b> 将第二个呼号复制到Dx Call,<br> + 定位器到Dx网格,将Rx和Tx频率更改为<br> + 解码信号的频率,并生成标准信息。<br> + <br/> + 如果勾选了<b>Hold Tx Freq</b>(保持发送频率)或第一条呼入消息<br> + 是你自己的呼号,发送频率不改变除非按住Ctrl键。<br/> + </td> + </tr> + <tr> + <td align="right">擦除按钮:</td> + <td><b>单击</b>可擦除通联窗口信息。<br/> + <b>双击</b>可擦除通联窗口和波段活动窗口信息。 + </td> + </tr> +</table> @@ -4341,7 +4414,7 @@ UDP 服务器 %2:%3 Unexpected rig error - 无线电设备意外出错误 + 无线电设备意外错误 @@ -4369,27 +4442,27 @@ UDP 服务器 %2:%3 Error reading waterfall palette file "%1:%2" too many colors. - 读取瀑布调色板文件时出错误 "%1:%2" 太多颜色. + 读取瀑布调色板文件时错误 "%1:%2" 太多颜色. Error reading waterfall palette file "%1:%2" invalid triplet. - 读取瀑布调色板文件时出错误 "%1:%2" 无效的三元组. + 读取瀑布调色板文件时错误 "%1:%2" 无效的三元组. Error reading waterfall palette file "%1:%2" invalid color. - 读取瀑布调色板文件时出错误 "%1:%2" 无效的颜色. + 读取瀑布调色板文件时错误 "%1:%2" 无效的颜色. Error opening waterfall palette file "%1": %2. - 读取瀑布调色板文件时出错误 "%1": %2. + 读取瀑布调色板文件时错误 "%1": %2. Error writing waterfall palette file "%1": %2. - 读取瀑布调色板文件时出错误 "%1": %2. + 读取瀑布调色板文件时错误 "%1": %2. @@ -4402,7 +4475,7 @@ UDP 服务器 %2:%3 File System Error - 文件系统出错误 + 文件系统错误 @@ -4413,7 +4486,7 @@ Error(%3): %4 无法重命名文件: "%1" 到: "%2" -出错误(%3): %4 +错误(%3): %4 @@ -4427,7 +4500,7 @@ Error(%3): %4 Network Error - 网络出错误 + 网络错误 @@ -4453,7 +4526,7 @@ Error(%3): %4 Error(%2): %3 无法打开文件: "%1" -出错误(%2): %3 +错误(%2): %3 @@ -4469,7 +4542,7 @@ Error(%2): %3 Error(%2): %3 无法写入文件: "%1" -出错误(%2): %3 +错误(%2): %3 @@ -4526,12 +4599,12 @@ Error(%2): %3 An error opening the audio input device has occurred. - 打开音频输入设备时出错误. + 打开音频输入设备时错误. An error occurred during read from the audio input device. - 从音频输入设备读取时出错误. + 从音频输入设备读取时错误. @@ -4541,7 +4614,7 @@ Error(%2): %3 Non-recoverable error, audio input device not usable at this time. - 不可恢复的出错误, 音频输入设备此时不可用. + 不可恢复的错误, 音频输入设备此时不可用. @@ -4609,7 +4682,7 @@ Error(%2): %3 Non-recoverable error, audio output device not usable at this time. - 不可恢复出错误, 音频输出设备此时不可用. + 不可恢复的错误, 音频输出设备此时不可用. @@ -4718,7 +4791,7 @@ Error(%2): %3 Unexpected rig error - 无线电设备意外出错误 + 无线电设备意外错误 @@ -4771,7 +4844,7 @@ Error(%2): %3 Spec - 佔高 + 占高 @@ -4896,7 +4969,7 @@ Error(%2): %3 Wide Graph - 宽图 + 宽瀑布图 @@ -4938,7 +5011,7 @@ Error(%2): %3 Genera&l - 一般(&l) + 常规(&l) @@ -4993,12 +5066,12 @@ Error(%2): %3 Message generation for type 2 compound callsign holders: - 信息生成用於類型2複合呼号持有人: + 信息生成用于类型2复合呼号持有人: <html><head/><body><p>Type 2 compound callsigns are those with prefixes or suffixes not included in the allowed shortlist (See Help-&gt;Add-on prefixes and suffixes).</p><p>This option determines which generated messages should contain your full type 2 compound call sign rather than your base callsign. It only applies if you have a type 2 compound callsign.</p><p>This option controls the way the messages that are used to answer CQ calls are generated. Generated messages 6 (CQ) and 5 (73) will always contain your full callsign. The JT65 and JT9 protocols allow for some standard messages with your full call at the expense of another piece of information such as the DX call or your locator.</p><p>Choosing message 1 omits the DX callsign which may be an issue when replying to CQ calls. Choosing message 3 also omits the DX callsign and many versions of this and other software will not extract the report. Choosing neither means that your full callsign only goes in your message 5 (73) so your QSO partner may log the wrong callsign.</p><p>None of these options are perfect, message 3 is usually best but be aware your QSO partner may not log the report you send them.</p></body></html> - <html><head/><body><p>复合呼号类型2是那些前缀或后缀不包括在允许的决选名单中 (请参阅帮助-& gt; 加载项前缀和后缀).<p><p>此选项确定哪些生成的信息应包含完整类型2复合呼号, 而不是基本呼号.它仅适用于类型为2的复合呼号.</p><p>此选项控制用于应答 CQ 呼叫的信息的生成方式.生成的信息 6 (CQ) 和 5 (73) 将始终包含您的完整呼号.jt65 和 jt9 协议允许在您的完整呼叫中使用一些标准信息, 而牺牲了另一条信息, 如 DX 呼叫或您的定位器.</p><p>选择信息1省略DX 呼号, 这在答复 CQ 呼叫时可能是一个问题.选择信息3也会省略 DX 呼号, 此软件和其他软件的许多版本都不会提取报告.选择这两个都意味着你的完整呼号只会出现在你的信息 5 (73) 中, 所以你的通联伙伴我的日志是出错误的呼号.</p><p>这些选项都不是完美的, 信息3是最好的, 但请注意, 您的通联合作伙伴可能不会记录您发送的报告.</p></body></html> + <html><head/><body><p>复合呼号类型2是那些前缀或后缀不包括在允许的决选名单中 (请参阅帮助-& gt; 加载项前缀和后缀).<p><p>此选项确定哪些生成的信息应包含完整类型2复合呼号, 而不是基本呼号.它仅适用于类型为2的复合呼号.</p><p>此选项控制用于应答 CQ 呼叫的信息的生成方式.生成的信息 6 (CQ) 和 5 (73) 将始终包含您的完整呼号.jt65 和 jt9 协议允许在您的完整呼叫中使用一些标准信息, 而牺牲了另一条信息, 如 DX 呼叫或您的定位器.</p><p>选择信息1省略DX 呼号, 这在答复 CQ 呼叫时可能是一个问题.选择信息3也会省略 DX 呼号, 此软件和其他软件的许多版本都不会提取报告.选择这两个都意味着你的完整呼号只会出现在你的信息 5 (73) 中, 所以你的通联伙伴我的日志是错误的呼号.</p><p>这些选项都不是完美的, 信息3是最好的, 但请注意, 您的通联合作伙伴可能不会记录您发送的报告.</p></body></html> @@ -5874,7 +5947,7 @@ comments field. d&B reports to comments - 把d&B报告写入注释栏 + 把d&B信号报告写入备注栏 diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index bb47a0ca7..c8c25553b 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -203,7 +203,7 @@ Freq(MHz) - 頻率(MHz) + 頻率(兆赫) @@ -398,7 +398,7 @@ path: "%1" - 目录: "%1" + 目錄: "%1" @@ -739,7 +739,7 @@ Format: U&nset background color - 未設定背景顏色(&n) + 清除底色(&n) @@ -903,7 +903,7 @@ Format: URL Error - 網址出錯誤 + 網址錯誤 @@ -922,12 +922,12 @@ Format: JSON Error - JSON出錯誤 + JSON錯誤 Contents file syntax error %1 at character offset %2 - 內容檔案語法出錯誤 %1 字符偏移量 %2 + 內容檔案語法錯誤 %1 字符偏移量 %2 @@ -937,7 +937,7 @@ Format: File System Error - 檔案系統出錯誤 + 檔案系統錯誤 @@ -974,7 +974,7 @@ Error: %2 - %3 Network Error - 網絡出錯誤 + 網絡錯誤 @@ -1083,7 +1083,7 @@ Error: %2 - %3 Freq (Hz) - 頻率 (Hz) + 頻率 (赫兹) @@ -1477,7 +1477,7 @@ Error: %2 - %3 Frequency (MHz) - 頻率 (MHz) + 頻率 (兆赫) @@ -1573,22 +1573,22 @@ Error: %2 - %3 Hamlib initialisation error - Hamlib 初始化出錯誤 + Hamlib 初始化錯誤 Hamlib settings file error: %1 at character offset %2 - Hamlib 設置檔案出錯誤: %1 字符偏移量 %2 + Hamlib 設置檔案錯誤: %1 字符偏移量 %2 Hamlib settings file error: top level must be a JSON object - Hamlib 設置檔案出錯誤: 頂層必須是 JSON 對象 + Hamlib 設置檔案錯誤: 頂層必須是 JSON 對象 Hamlib settings file error: config must be a JSON object - Hamlib 設置檔案出錯誤: 配置必須是JSON對象 + Hamlib 設置檔案錯誤: 配置必須是JSON對象 @@ -1598,7 +1598,7 @@ Error: %2 - %3 Hamlib error: %1 while %2 - Hamlib 出錯誤: %1 當 %2 + Hamlib 錯誤: %1 當 %2 @@ -2092,7 +2092,7 @@ Error(%2): %3 Log &QSO - 紀錄通聯(&Q) + 記錄通聯(&Q) @@ -2112,7 +2112,7 @@ Error(%2): %3 &Monitor - 监听(&M) + 監聽(&M) @@ -2489,7 +2489,7 @@ Yellow when too low Frequency tolerance (Hz) - 頻率容差 (Hz) + 頻率容差 (赫兹) @@ -2617,7 +2617,7 @@ Yellow when too low Frequency to call CQ on in kHz above the current MHz - 呼叫CQ 的頻率以 kHz 高於目前的 MHz + 呼叫 CQ 的頻率以千赫高於目前的兆赫 @@ -2704,12 +2704,12 @@ When not checked you can view the calibration results. <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - <html><head/><body><p>信號報告: 參考2500 Hz 頻寬 (dB) 中的信噪比.</p></body></html> + <html><head/><body><p>信號報告: 參考2500赫兹頻寬 (dB) 中的信噪比.</p></body></html> Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - 信號報告: 參考2500 Hz 頻寬 (dB) 中的信噪比. + 信號報告: 參考2500赫兹頻寬 (dB) 中的信噪比. @@ -3583,7 +3583,7 @@ list. The list can be maintained in Settings (F2). Color highlighting scheme - 色彩突顯機制 + 顏色突出顯示方案 @@ -3660,7 +3660,7 @@ list. The list can be maintained in Settings (F2). Enumerating audio devices - + 列舉音訊設備 @@ -3703,7 +3703,7 @@ list. The list can be maintained in Settings (F2). Error removing "%1" - 刪除時出錯誤 "%1" + 刪除時錯誤 "%1" @@ -3720,7 +3720,7 @@ list. The list can be maintained in Settings (F2). File Open Error - 檔案開啟出錯誤 + 檔案開啟錯誤 @@ -3734,17 +3734,17 @@ list. The list can be maintained in Settings (F2). Error saving c2 file - 保存c2檔案出錯誤 + 保存c2檔案錯誤 Error in Sound Input - 聲音輸入出錯誤 + 聲音輸入錯誤 Error in Sound Output - 聲音輸出錯誤 + 聲音輸錯誤 @@ -3784,7 +3784,7 @@ list. The list can be maintained in Settings (F2). Subprocess Error - 子流程出錯誤 + 子流程錯誤 @@ -3802,7 +3802,7 @@ list. The list can be maintained in Settings (F2). Subprocess error - 子進程出錯誤 + 子進程錯誤 @@ -3841,7 +3841,7 @@ list. The list can be maintained in Settings (F2). No data read from disk. Wrong file format? - 沒有從磁盤讀取數據. 檔案格式出錯誤? + 沒有從磁盤讀取數據. 檔案格式錯誤? @@ -3955,7 +3955,51 @@ list. The list can be maintained in Settings (F2). <tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr> </table> Keyboard shortcuts help window contents - + <table cellspacing=1> + <tr><td><b>Esc </b></td><td>停止發送,中止通聯,清除下一個呼叫隊列</td></tr> + <tr><td><b>F1 </b></td><td>在線用戶指南 (Alt: 發射 Tx6)</td></tr> + <tr><td><b>Shift+F1 </b></td><td>版權聲明</td></tr> + <tr><td><b>Ctrl+F1 </b></td><td>關於 WSJT-X</td></tr> + <tr><td><b>F2 </b></td><td>打開設置窗口 (Alt: 發射 Tx2)</td></tr> + <tr><td><b>F3 </b></td><td>顯示鍵盤快捷鍵 (Alt: 發射 Tx3)</td></tr> + <tr><td><b>F4 </b></td><td>清除DX呼號, DX網格, 發射信息 1-4 (Alt: 發射 Tx4)</td></tr> + <tr><td><b>Alt+F4 </b></td><td>退出程序</td></tr> + <tr><td><b>F5 </b></td><td>顯示特殊鼠標命令 (Alt: transmit Tx5)</td></tr> + <tr><td><b>F6 </b></td><td>打開目錄中下一個文件 (Alt: toggle "Call 1st")</td></tr> + <tr><td><b>Shift+F6 </b></td><td>直接解碼所有剩餘檔</td></tr> + <tr><td><b>F7 </b></td><td>顯示信息平均視窗</td></tr> + <tr><td><b>F11 </b></td><td>將發射頻率向下移動 1 赫茲</td></tr> + <tr><td><b>Ctrl+F11 </b></td><td>移動相同的 接收 和 發射頻率向下移動 1 赫茲</td></tr> + <tr><td><b>Shift+F11 </b></td><td>將發射頻率向下移動 60 赫茲 (FT8) 或 90 赫茲 (FT4)</td></tr> + <tr><td><b>Ctrl+Shift+F11 </b></td><td>將頻率向下移動 2000 赫茲</td></tr> + <tr><td><b>F12 </b></td><td>將接收頻率向上移動 1 赫茲</td></tr> + <tr><td><b>Ctrl+F12 </b></td><td>相同的接收和發射頻率向上 1 赫茲</td></tr> + <tr><td><b>Shift+F12 </b></td><td>將發射頻率向上移動 60 赫茲(FT8) or 90 赫茲 (FT4)</td></tr> + <tr><td><b>Ctrl+Shift+F12 </b></td><td>將頻率調高 2000 赫茲</td></tr> + <tr><td><b>Alt+1-6 </b></td><td>現在將傳輸設置為選項卡 1 上的此號碼</td></tr> + <tr><td><b>Ctl+1-6 </b></td><td>在選項卡 1 上將下一個傳輸設置為此號碼</td></tr> + <tr><td><b>Alt+B </b></td><td>切換 "最佳 S+P" 狀態</td></tr> + <tr><td><b>Alt+C </b></td><td>切換 "呼叫 CQ 強制呼叫第 1" 複選框</td></tr> + <tr><td><b>Alt+D </b></td><td>在通聯頻率再次解碼</td></tr> + <tr><td><b>Shift+D </b></td><td>全部解碼(兩個視窗)</td></tr> + <tr><td><b>Ctrl+E </b></td><td>打開 TX even/1st</td></tr> + <tr><td><b>Shift+E </b></td><td>關閉 TX even/1st</td></tr> + <tr><td><b>Alt+E </b></td><td>擦除</td></tr> + <tr><td><b>Ctrl+F </b></td><td>編輯自訂義文字資訊</td></tr> + <tr><td><b>Alt+G </b></td><td>生成標準信息</td></tr> + <tr><td><b>Alt+H </b></td><td>停止發射</td></tr> + <tr><td><b>Ctrl+L </b></td><td>在資料庫中尋找呼號, 生成標準信息</td></tr> + <tr><td><b>Alt+M </b></td><td>監聽</td></tr> + <tr><td><b>Alt+N </b></td><td>啟用發射</td></tr> + <tr><td><b>Ctrl+O </b></td><td>打開 .wav 檔案</td></tr> + <tr><td><b>Alt+O </b></td><td>更換操作員</td></tr> + <tr><td><b>Alt+Q </b></td><td>記錄通聯</td></tr> + <tr><td><b>Ctrl+R </b></td><td>將 Tx4 訊息設定為 RRR(不在 FT4 中)</td></tr> + <tr><td><b>Alt+R </b></td><td>將 Tx4 消息設置為 RR73</td></tr> + <tr><td><b>Alt+S </b></td><td>停止監聽</td></tr> + <tr><td><b>Alt+T </b></td><td>切換調諧狀態</td></tr> + <tr><td><b>Alt+Z </b></td><td>清除掛起解碼器狀態</td></tr> +</table> @@ -3991,7 +4035,37 @@ list. The list can be maintained in Settings (F2). </tr> </table> Mouse commands help window contents - + <table cellpadding=5> + <tr> + <th align="right">點擊</th> + <th align="left">行動</th> + </tr> + <tr> + <td align="right">瀑布圖:</td> + <td><b>Click</b> 設置接收頻率.<br/> + <b>Shift-click</b> 設置發射頻率.<br/> + <b>Ctrl-click</b> or <b>右鍵單擊</b> 設置接收和發射頻率.<br/> + <b>Double-click</b> 在接收頻率解碼.<br/> + </td> + </tr> + <tr> + <td align="right">解碼文字:</td> + <td><b>Double-click</b> 解碼的文字將第二個呼號複製到 Dx 呼號,<br/> + 定位器到 Dx 網格,將接收和發射頻率更改為<br/> + 解碼信號的頻率, 並生成<br/> + 標準信息.<br/> + 如果 <b>保持發射頻率</b> 已選中或在消息中顯示第一個呼號<br/> + 是你自己的呼叫, 發射頻率不更改,除非 <br/> + <b>Ctrl</b> 鍵被按下.<br/> + </td> + </tr> + <tr> + <td align="right">擦除按鈕:</td> + <td><b>點擊</b> 擦除通聯視窗.<br/> + <b>按兩下</b> to erase QSO and Band Activity windows. + </td> + </tr> +</table> @@ -4341,7 +4415,7 @@ UDP 服務器 %2:%3 Unexpected rig error - 無線電設備意外出錯誤 + 無線電設備意外錯誤 @@ -4369,27 +4443,27 @@ UDP 服務器 %2:%3 Error reading waterfall palette file "%1:%2" too many colors. - 讀取瀑布調色板檔案時出錯誤 "%1:%2" 太多顏色. + 讀取瀑布調色板檔案時錯誤 "%1:%2" 太多顏色. Error reading waterfall palette file "%1:%2" invalid triplet. - 讀取瀑布調色板檔案時出錯誤 "%1:%2" 無效的三元組. + 讀取瀑布調色板檔案時錯誤 "%1:%2" 無效的三元組. Error reading waterfall palette file "%1:%2" invalid color. - 讀取瀑布調色板檔案時出錯誤 "%1:%2" 無效的顏色. + 讀取瀑布調色板檔案時錯誤 "%1:%2" 無效的顏色. Error opening waterfall palette file "%1": %2. - 讀取瀑布調色板檔案時出錯誤 "%1": %2. + 讀取瀑布調色板檔案時錯誤 "%1": %2. Error writing waterfall palette file "%1": %2. - 讀取瀑布調色板檔案時出錯誤 "%1": %2. + 讀取瀑布調色板檔案時錯誤 "%1": %2. @@ -4402,7 +4476,7 @@ UDP 服務器 %2:%3 File System Error - 檔案系統出錯誤 + 檔案系統錯誤 @@ -4413,7 +4487,7 @@ Error(%3): %4 無法重命名檔案: "%1" 到: "%2" -出錯誤(%3): %4 +錯誤(%3): %4 @@ -4453,7 +4527,7 @@ Error(%3): %4 Error(%2): %3 無法開啟檔案: "%1" -出錯誤(%2): %3 +錯誤(%2): %3 @@ -4469,7 +4543,7 @@ Error(%2): %3 Error(%2): %3 無法寫入檔案: "%1" -出錯誤(%2): %3 +錯誤(%2): %3 @@ -4508,7 +4582,7 @@ Error(%2): %3 Check this if you get SSL/TLS errors - 如果您收到SSL/TLS錯誤, 請選擇此項 + 如果您得到SSL/TLS錯誤, 請選擇此項 @@ -4526,12 +4600,12 @@ Error(%2): %3 An error opening the audio input device has occurred. - 開啟音頻輸入設備時出錯誤. + 開啟音頻輸入設備時錯誤. An error occurred during read from the audio input device. - 從音頻輸入設備讀取時出錯誤. + 從音頻輸入設備讀取時錯誤. @@ -4541,7 +4615,7 @@ Error(%2): %3 Non-recoverable error, audio input device not usable at this time. - 不可恢復的出錯誤, 音頻輸入設備此時不可用. + 不可恢復的錯誤, 音頻輸入設備此時不可用. @@ -4718,7 +4792,7 @@ Error(%2): %3 Unexpected rig error - 無線電設備意外出錯誤 + 無線電設備意外錯誤 @@ -4998,7 +5072,7 @@ Error(%2): %3 <html><head/><body><p>Type 2 compound callsigns are those with prefixes or suffixes not included in the allowed shortlist (See Help-&gt;Add-on prefixes and suffixes).</p><p>This option determines which generated messages should contain your full type 2 compound call sign rather than your base callsign. It only applies if you have a type 2 compound callsign.</p><p>This option controls the way the messages that are used to answer CQ calls are generated. Generated messages 6 (CQ) and 5 (73) will always contain your full callsign. The JT65 and JT9 protocols allow for some standard messages with your full call at the expense of another piece of information such as the DX call or your locator.</p><p>Choosing message 1 omits the DX callsign which may be an issue when replying to CQ calls. Choosing message 3 also omits the DX callsign and many versions of this and other software will not extract the report. Choosing neither means that your full callsign only goes in your message 5 (73) so your QSO partner may log the wrong callsign.</p><p>None of these options are perfect, message 3 is usually best but be aware your QSO partner may not log the report you send them.</p></body></html> - <html><head/><body><p>複合呼號類型2是那些前綴或後綴不包括在允許的決選名單中 (請參閱説明-& gt; 載入項目前綴和後綴).<p><p>這個選項確定哪些產生的資訊應包含完整類型2複合呼號, 而不是基本呼號.它僅適用於類型為2的複合呼號.</p><p>這個選項控制用於應答 CQ 呼叫的資訊產生方式.產生的資訊 6 (CQ) 和 5 (73) 將始終包含您的完整呼號.jt65 和 jt9 協定允許在您的完整呼叫中使用一些標準資訊, 而犧牲了另一條資訊, 如 DX 呼叫或您的定位.</p><p>選擇資訊1省略 DX 呼號, 這在答覆 CQ 呼叫時可能是一個問題.選擇資訊3也會省略 DX 呼號, 此軟體和其他軟體的許多版本都不會提取報告.選擇這兩個都意味著你的完整呼號只會出現在你的資訊 5 (73) 中, 所以你的通聯夥伴我的日誌是出錯誤的呼號.</p><p>這些選項都不是完美的, 資訊 3 是最好的, 但請注意, 您的通聯合作夥伴可能不會記錄您傳送的報告.</p></body></html> + <html><head/><body><p>複合呼號類型2是那些前綴或後綴不包括在允許的決選名單中 (請參閱説明-& gt; 載入項目前綴和後綴).<p><p>這個選項確定哪些產生的資訊應包含完整類型2複合呼號, 而不是基本呼號.它僅適用於類型為2的複合呼號.</p><p>這個選項控制用於應答 CQ 呼叫的資訊產生方式.產生的資訊 6 (CQ) 和 5 (73) 將始終包含您的完整呼號.jt65 和 jt9 協定允許在您的完整呼叫中使用一些標準資訊, 而犧牲了另一條資訊, 如 DX 呼叫或您的定位.</p><p>選擇資訊1省略 DX 呼號, 這在答覆 CQ 呼叫時可能是一個問題.選擇資訊3也會省略 DX 呼號, 此軟體和其他軟體的許多版本都不會提取報告.選擇這兩個都意味著你的完整呼號只會出現在你的資訊 5 (73) 中, 所以你的通聯夥伴我的日誌是錯誤的呼號.</p><p>這些選項都不是完美的, 資訊 3 是最好的, 但請注意, 您的通聯合作夥伴可能不會記錄您傳送的報告.</p></body></html> @@ -5531,7 +5605,7 @@ or bandwidth is selected). None - + From 9b634c9a2b16b2e99fb0d8c14f1d3d3c162fe5cb Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sat, 7 Nov 2020 13:42:42 +0000 Subject: [PATCH 49/73] Updated Chinese and Hong Kong UI translations, tnx Sze-to, VR2UPU --- translations/wsjtx_zh.ts | 185 +++++++++++++++++++++++++----------- translations/wsjtx_zh_HK.ts | 174 +++++++++++++++++++++++---------- 2 files changed, 253 insertions(+), 106 deletions(-) diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index 05f8a773a..5a9824c8d 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -203,7 +203,7 @@ Freq(MHz) - 频率(MHz) + 频率(兆赫) @@ -807,22 +807,22 @@ Format: New CQ Zone - 新 CQ Zone + 新 CQ 区 New CQ Zone on Band - 新 CQ Zone 波段 + 新 CQ 区 波段 New ITU Zone - 新 ITU Zone + 新 ITU 区 New ITU Zone on Band - 新 ITU Zone 波段 + 新 ITU 区 波段 @@ -832,7 +832,7 @@ Format: f/g unset - 字體颜色未设置 + 字体颜色未设置 @@ -903,7 +903,7 @@ Format: URL Error - 网址出错误 + 网址错误 @@ -922,12 +922,12 @@ Format: JSON Error - JSON出错误 + JSON错误 Contents file syntax error %1 at character offset %2 - 内容文件语法出错误 %1 字符偏移量 %2 + 内容文件语法错误 %1 字符偏移量 %2 @@ -937,14 +937,14 @@ Format: File System Error - 文件系统出错误 + 文件系统错误 Failed to open "%1" Error: %2 - %3 未能打开 "%1" -出错误: %2 - %3 +错误: %2 - %3 @@ -974,7 +974,7 @@ Error: %2 - %3 Network Error - 网络出错误 + 网络错误 @@ -1083,7 +1083,7 @@ Error: %2 - %3 Freq (Hz) - 频率 (Hz) + 频率 (赫兹) @@ -1477,7 +1477,7 @@ Error: %2 - %3 Frequency (MHz) - 频率 (MHz) + 频率 (兆赫) @@ -1573,22 +1573,22 @@ Error: %2 - %3 Hamlib initialisation error - Hamlib 初始化出错误 + Hamlib 初始化错误 Hamlib settings file error: %1 at character offset %2 - Hamlib 设置文件出错误: %1 字符偏移量 %2 + Hamlib 设置文件错误: %1 字符偏移量 %2 Hamlib settings file error: top level must be a JSON object - Hamlib 设置文件出错误: 顶层必须是 JSON 对象 + Hamlib 设置文件错误: 顶层必须是 JSON 对象 Hamlib settings file error: config must be a JSON object - Hamlib 设置文件出错误: 配置必须是JSON对象 + Hamlib 设置文件错误: 配置必须是JSON对象 @@ -1598,7 +1598,7 @@ Error: %2 - %3 Hamlib error: %1 while %2 - Hamlib 出错误: %1 当 %2 + Hamlib 错误: %1 当 %2 @@ -2092,7 +2092,7 @@ Error(%2): %3 Log &QSO - 纪录通联(&Q) + 记录通联(&Q) @@ -2433,7 +2433,7 @@ Yellow when too low Select operating band or enter frequency in MHz or enter kHz increment followed by k. - 选择工作频段或输入 MHz 频率或输入 kHz 增量,然后输入 k. + 选择工作频段或输入兆赫频率或输入千赫增量, 然后输入 k. @@ -2489,7 +2489,7 @@ Yellow when too low Frequency tolerance (Hz) - 频率容差 (Hz) + 频率容差 (赫兹) @@ -2617,7 +2617,7 @@ Yellow when too low Frequency to call CQ on in kHz above the current MHz - 呼叫 CQ 的频率以 kHz 高于当前的 MHz + 呼叫 CQ 的频率以千赫高于当前的兆赫 @@ -2704,12 +2704,12 @@ When not checked you can view the calibration results. <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - <html><head/><body><p>信号报告: 参考2500 Hz 带宽 (dB) 中的信噪比.</p></body></html> + <html><head/><body><p>信号报告: 参考2500赫兹带宽 (分贝) 中的信噪比.</p></body></html> Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - 信号报告: 参考2500 Hz 带宽 (dB) 中的信噪比. + 信号报告: 参考2500赫兹带宽 (分贝) 中的信噪比. @@ -3282,7 +3282,7 @@ list. The list can be maintained in Settings (F2). About WSJT-X - 有关 WSJT-X + 关于 WSJT-X @@ -3342,7 +3342,7 @@ list. The list can be maintained in Settings (F2). Special mouse commands - 滑鼠特殊组合 + 特殊鼠标动作 @@ -3583,7 +3583,7 @@ list. The list can be maintained in Settings (F2). Color highlighting scheme - 颜色突显方案 + 颜色突出显示方案 @@ -3660,7 +3660,7 @@ list. The list can be maintained in Settings (F2). Enumerating audio devices - + 列举音频设备 @@ -3703,7 +3703,7 @@ list. The list can be maintained in Settings (F2). Error removing "%1" - 删除时出错误 "%1" + 删除时错误 "%1" @@ -3720,7 +3720,7 @@ list. The list can be maintained in Settings (F2). File Open Error - 文件打开出错误 + 文件打开错误 @@ -3861,7 +3861,7 @@ list. The list can be maintained in Settings (F2). Special Mouse Commands - 滑鼠特殊组合 + 特殊鼠标组合 @@ -3955,7 +3955,51 @@ list. The list can be maintained in Settings (F2). <tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr> </table> Keyboard shortcuts help window contents - + <table cellspacing=1> +<tr><td><b>Esc</b></td><td>停止发送, 中止通联, 清除下一个呼叫队列</td></tr> +<tr><td><b>F1</b></td><td>联机用户指南(Alt:transmitTx6)</td></tr> +<tr><td><b>Shift+F1</b></td><td>版权声明</td></tr> +<tr><td><b>Ctrl+F1</b></td><td>关于WSJT-X</td></tr> +<tr><td><b>F2</b></td><td>打开设置窗口(Alt:transmitTx2)</td></tr> +<tr><td><b>F3</b></td><td>显示键盘快捷键(Alt:transmitTx3)</td></tr> +<tr><td><b>F4</b></td><td>清除DX呼叫, DX网格, Tx消息1-4(Alt:发送Tx4)</td></tr> +<tr><td><b>Alt+F4</b></td><td>退出程序</td></tr> +<tr><td><b>F5</b></td><td>显示特殊鼠标命令(Alt:发送Tx5)</td></tr> +<tr><td><b>F6</b></td><td>打开目录中的下一个文件(Alt:toggle“Call1st”)</td></tr> +<tr><td><b>Shift+F6</b></td><td>在目录中解码所有剩余的文件</td></tr> +<tr><td><b>F7</b></td><td>显示消息平均窗口</td></tr> +<tr><td><b>F11</b></td><td>将接收频率下移1赫兹</td></tr> +<tr><td><b>Ctrl+F11</b></td><td>将相同的接收和发送频率下移1赫兹</td></tr> +<tr><td><b>Shift+F11</b></td><td>将发送频率下移60赫兹(FT8)或90赫兹(FT4)</td></tr> +<tr><td><b>Ctrl+Shift+F11</b></td><td>降低拨号频率2000赫兹</td></tr> +<tr><td><b>F12</b></td><td>将接收频率上移1赫兹</td></tr> +<tr><td><b>Ctrl+F12</b></td><td>将相同的接收和发送频率向上移动1赫兹</td></tr> +<tr><td><b>Shift+F12</b></td><td>将发送频率上移60赫兹(FT8)或90赫兹(FT4)</td></tr> +<tr><td><b>Ctrl+Shift+F12</b></td><td>将拨号频率向上移动2000赫兹</td></tr> +<tr><td><b>Alt+1-6</b></td><td>现在将变速器设置为表1上的此号码</td></tr> +<tr><td><b>Ctl+1-6</b></td><td>将下一次传输设置为选项卡1上的此号码</td></tr> +<tr><td><b>Alt+B</b></td><td>切换“最佳S+P”状态</td></tr> +<tr><td><b>Alt+C</b></td><td>切换“第一次呼叫”复选框</td></tr> +<tr><td><b>Alt+D</b></td><td>以通联频率再次解码</td></tr> +<tr><td><b>Shift+D</b></td><td>完全解码(两个窗口)</td></tr> +<tr><td><b>Ctrl+E</b></td><td>打开TXeven/1st</td></tr> +<tr><td><b>Shift+E</b></td><td>关闭TXeven/1st</td></tr> +<tr><td><b>Alt+E</b></td><td>擦除</td></tr> +<tr><td><b>Ctrl+F</b></td><td>编辑自定义文本信息框</td></tr> +<tr><td><b>Alt+G</b></td><td>生成标准消息</td></tr> +<tr><td><b>Alt+H</b></td><td>停止发送</td></tr> +<tr><td><b>Ctrl+L</b></td><td>在数据库中查找呼号, 生成标准消息</td></tr> +<tr><td><b>Alt+M</b></td><td>监听</td></tr> +<tr><td><b>Alt+N</b></td><td>启用发送</td></tr> +<tr><td><b>Ctrl+O</b></td><td>打开.wav文件</td></tr> +<tr><td><b>Alt+O</b></td><td>更换操作员</td></tr> +<tr><td><b>Alt+Q</b></td><td>记录通联</td></tr> +<tr><td><b>Ctrl+R</b></td><td>将Tx4信息设置为RRR(不在FT4中)</td></tr> +<tr><td><b>Alt+R</b></td><td>将Tx4信息设置为RR73</td></tr> +<tr><td><b>Alt+S</b></td><td>停止监听</td></tr> +<tr><td><b>Alt+T</b></td><td>切换调谐状态</td></tr> +<tr><td><b>Alt+Z</b></td><td>清除挂起解码器状态</td></tr> +</table> @@ -3991,7 +4035,36 @@ list. The list can be maintained in Settings (F2). </tr> </table> Mouse commands help window contents - + <table cellpadding=5> + <tr> + <th align="right">点击</th> + <th align="left">动作</th> + </tr> + <tr> + <td align="right">瀑布图:</td> + <td><b>单击 </b>设置接收频率。<br> + <b>按住Shift键单击 </b>可设置发送频率。<br> + <b>按住Ctrl键单击或右键单击 </b>可设置接收和发送频率。<br> + <b>双击</b> 可以在接收频率解码。<br/> + </td> + </tr> + <tr> + <td align="right">解码信息:</td> + <td><b>双击</b> 将第二个呼号复制到Dx Call,<br> + 定位器到Dx网格,将Rx和Tx频率更改为<br> + 解码信号的频率,并生成标准信息。<br> + <br/> + 如果勾选了<b>Hold Tx Freq</b>(保持发送频率)或第一条呼入消息<br> + 是你自己的呼号,发送频率不改变除非按住Ctrl键。<br/> + </td> + </tr> + <tr> + <td align="right">擦除按钮:</td> + <td><b>单击</b>可擦除通联窗口信息。<br/> + <b>双击</b>可擦除通联窗口和波段活动窗口信息。 + </td> + </tr> +</table> @@ -4341,7 +4414,7 @@ UDP 服务器 %2:%3 Unexpected rig error - 无线电设备意外出错误 + 无线电设备意外错误 @@ -4369,27 +4442,27 @@ UDP 服务器 %2:%3 Error reading waterfall palette file "%1:%2" too many colors. - 读取瀑布调色板文件时出错误 "%1:%2" 太多颜色. + 读取瀑布调色板文件时错误 "%1:%2" 太多颜色. Error reading waterfall palette file "%1:%2" invalid triplet. - 读取瀑布调色板文件时出错误 "%1:%2" 无效的三元组. + 读取瀑布调色板文件时错误 "%1:%2" 无效的三元组. Error reading waterfall palette file "%1:%2" invalid color. - 读取瀑布调色板文件时出错误 "%1:%2" 无效的颜色. + 读取瀑布调色板文件时错误 "%1:%2" 无效的颜色. Error opening waterfall palette file "%1": %2. - 读取瀑布调色板文件时出错误 "%1": %2. + 读取瀑布调色板文件时错误 "%1": %2. Error writing waterfall palette file "%1": %2. - 读取瀑布调色板文件时出错误 "%1": %2. + 读取瀑布调色板文件时错误 "%1": %2. @@ -4402,7 +4475,7 @@ UDP 服务器 %2:%3 File System Error - 文件系统出错误 + 文件系统错误 @@ -4413,7 +4486,7 @@ Error(%3): %4 无法重命名文件: "%1" 到: "%2" -出错误(%3): %4 +错误(%3): %4 @@ -4427,7 +4500,7 @@ Error(%3): %4 Network Error - 网络出错误 + 网络错误 @@ -4453,7 +4526,7 @@ Error(%3): %4 Error(%2): %3 无法打开文件: "%1" -出错误(%2): %3 +错误(%2): %3 @@ -4469,7 +4542,7 @@ Error(%2): %3 Error(%2): %3 无法写入文件: "%1" -出错误(%2): %3 +错误(%2): %3 @@ -4526,12 +4599,12 @@ Error(%2): %3 An error opening the audio input device has occurred. - 打开音频输入设备时出错误. + 打开音频输入设备时错误. An error occurred during read from the audio input device. - 从音频输入设备读取时出错误. + 从音频输入设备读取时错误. @@ -4541,7 +4614,7 @@ Error(%2): %3 Non-recoverable error, audio input device not usable at this time. - 不可恢复的出错误, 音频输入设备此时不可用. + 不可恢复的错误, 音频输入设备此时不可用. @@ -4609,7 +4682,7 @@ Error(%2): %3 Non-recoverable error, audio output device not usable at this time. - 不可恢复出错误, 音频输出设备此时不可用. + 不可恢复的错误, 音频输出设备此时不可用. @@ -4718,7 +4791,7 @@ Error(%2): %3 Unexpected rig error - 无线电设备意外出错误 + 无线电设备意外错误 @@ -4771,7 +4844,7 @@ Error(%2): %3 Spec - 佔高 + 占高 @@ -4896,7 +4969,7 @@ Error(%2): %3 Wide Graph - 宽图 + 宽瀑布图 @@ -4938,7 +5011,7 @@ Error(%2): %3 Genera&l - 一般(&l) + 常规(&l) @@ -4993,12 +5066,12 @@ Error(%2): %3 Message generation for type 2 compound callsign holders: - 信息生成用於類型2複合呼号持有人: + 信息生成用于类型2复合呼号持有人: <html><head/><body><p>Type 2 compound callsigns are those with prefixes or suffixes not included in the allowed shortlist (See Help-&gt;Add-on prefixes and suffixes).</p><p>This option determines which generated messages should contain your full type 2 compound call sign rather than your base callsign. It only applies if you have a type 2 compound callsign.</p><p>This option controls the way the messages that are used to answer CQ calls are generated. Generated messages 6 (CQ) and 5 (73) will always contain your full callsign. The JT65 and JT9 protocols allow for some standard messages with your full call at the expense of another piece of information such as the DX call or your locator.</p><p>Choosing message 1 omits the DX callsign which may be an issue when replying to CQ calls. Choosing message 3 also omits the DX callsign and many versions of this and other software will not extract the report. Choosing neither means that your full callsign only goes in your message 5 (73) so your QSO partner may log the wrong callsign.</p><p>None of these options are perfect, message 3 is usually best but be aware your QSO partner may not log the report you send them.</p></body></html> - <html><head/><body><p>复合呼号类型2是那些前缀或后缀不包括在允许的决选名单中 (请参阅帮助-& gt; 加载项前缀和后缀).<p><p>此选项确定哪些生成的信息应包含完整类型2复合呼号, 而不是基本呼号.它仅适用于类型为2的复合呼号.</p><p>此选项控制用于应答 CQ 呼叫的信息的生成方式.生成的信息 6 (CQ) 和 5 (73) 将始终包含您的完整呼号.jt65 和 jt9 协议允许在您的完整呼叫中使用一些标准信息, 而牺牲了另一条信息, 如 DX 呼叫或您的定位器.</p><p>选择信息1省略DX 呼号, 这在答复 CQ 呼叫时可能是一个问题.选择信息3也会省略 DX 呼号, 此软件和其他软件的许多版本都不会提取报告.选择这两个都意味着你的完整呼号只会出现在你的信息 5 (73) 中, 所以你的通联伙伴我的日志是出错误的呼号.</p><p>这些选项都不是完美的, 信息3是最好的, 但请注意, 您的通联合作伙伴可能不会记录您发送的报告.</p></body></html> + <html><head/><body><p>复合呼号类型2是那些前缀或后缀不包括在允许的决选名单中 (请参阅帮助-& gt; 加载项前缀和后缀).<p><p>此选项确定哪些生成的信息应包含完整类型2复合呼号, 而不是基本呼号.它仅适用于类型为2的复合呼号.</p><p>此选项控制用于应答 CQ 呼叫的信息的生成方式.生成的信息 6 (CQ) 和 5 (73) 将始终包含您的完整呼号.jt65 和 jt9 协议允许在您的完整呼叫中使用一些标准信息, 而牺牲了另一条信息, 如 DX 呼叫或您的定位器.</p><p>选择信息1省略DX 呼号, 这在答复 CQ 呼叫时可能是一个问题.选择信息3也会省略 DX 呼号, 此软件和其他软件的许多版本都不会提取报告.选择这两个都意味着你的完整呼号只会出现在你的信息 5 (73) 中, 所以你的通联伙伴我的日志是错误的呼号.</p><p>这些选项都不是完美的, 信息3是最好的, 但请注意, 您的通联合作伙伴可能不会记录您发送的报告.</p></body></html> @@ -5874,7 +5947,7 @@ comments field. d&B reports to comments - 把d&B报告写入注释栏 + 把d&B信号报告写入备注栏 diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index bb47a0ca7..c8c25553b 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -203,7 +203,7 @@ Freq(MHz) - 頻率(MHz) + 頻率(兆赫) @@ -398,7 +398,7 @@ path: "%1" - 目录: "%1" + 目錄: "%1" @@ -739,7 +739,7 @@ Format: U&nset background color - 未設定背景顏色(&n) + 清除底色(&n) @@ -903,7 +903,7 @@ Format: URL Error - 網址出錯誤 + 網址錯誤 @@ -922,12 +922,12 @@ Format: JSON Error - JSON出錯誤 + JSON錯誤 Contents file syntax error %1 at character offset %2 - 內容檔案語法出錯誤 %1 字符偏移量 %2 + 內容檔案語法錯誤 %1 字符偏移量 %2 @@ -937,7 +937,7 @@ Format: File System Error - 檔案系統出錯誤 + 檔案系統錯誤 @@ -974,7 +974,7 @@ Error: %2 - %3 Network Error - 網絡出錯誤 + 網絡錯誤 @@ -1083,7 +1083,7 @@ Error: %2 - %3 Freq (Hz) - 頻率 (Hz) + 頻率 (赫兹) @@ -1477,7 +1477,7 @@ Error: %2 - %3 Frequency (MHz) - 頻率 (MHz) + 頻率 (兆赫) @@ -1573,22 +1573,22 @@ Error: %2 - %3 Hamlib initialisation error - Hamlib 初始化出錯誤 + Hamlib 初始化錯誤 Hamlib settings file error: %1 at character offset %2 - Hamlib 設置檔案出錯誤: %1 字符偏移量 %2 + Hamlib 設置檔案錯誤: %1 字符偏移量 %2 Hamlib settings file error: top level must be a JSON object - Hamlib 設置檔案出錯誤: 頂層必須是 JSON 對象 + Hamlib 設置檔案錯誤: 頂層必須是 JSON 對象 Hamlib settings file error: config must be a JSON object - Hamlib 設置檔案出錯誤: 配置必須是JSON對象 + Hamlib 設置檔案錯誤: 配置必須是JSON對象 @@ -1598,7 +1598,7 @@ Error: %2 - %3 Hamlib error: %1 while %2 - Hamlib 出錯誤: %1 當 %2 + Hamlib 錯誤: %1 當 %2 @@ -2092,7 +2092,7 @@ Error(%2): %3 Log &QSO - 紀錄通聯(&Q) + 記錄通聯(&Q) @@ -2112,7 +2112,7 @@ Error(%2): %3 &Monitor - 监听(&M) + 監聽(&M) @@ -2489,7 +2489,7 @@ Yellow when too low Frequency tolerance (Hz) - 頻率容差 (Hz) + 頻率容差 (赫兹) @@ -2617,7 +2617,7 @@ Yellow when too low Frequency to call CQ on in kHz above the current MHz - 呼叫CQ 的頻率以 kHz 高於目前的 MHz + 呼叫 CQ 的頻率以千赫高於目前的兆赫 @@ -2704,12 +2704,12 @@ When not checked you can view the calibration results. <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - <html><head/><body><p>信號報告: 參考2500 Hz 頻寬 (dB) 中的信噪比.</p></body></html> + <html><head/><body><p>信號報告: 參考2500赫兹頻寬 (dB) 中的信噪比.</p></body></html> Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - 信號報告: 參考2500 Hz 頻寬 (dB) 中的信噪比. + 信號報告: 參考2500赫兹頻寬 (dB) 中的信噪比. @@ -3583,7 +3583,7 @@ list. The list can be maintained in Settings (F2). Color highlighting scheme - 色彩突顯機制 + 顏色突出顯示方案 @@ -3660,7 +3660,7 @@ list. The list can be maintained in Settings (F2). Enumerating audio devices - + 列舉音訊設備 @@ -3703,7 +3703,7 @@ list. The list can be maintained in Settings (F2). Error removing "%1" - 刪除時出錯誤 "%1" + 刪除時錯誤 "%1" @@ -3720,7 +3720,7 @@ list. The list can be maintained in Settings (F2). File Open Error - 檔案開啟出錯誤 + 檔案開啟錯誤 @@ -3734,17 +3734,17 @@ list. The list can be maintained in Settings (F2). Error saving c2 file - 保存c2檔案出錯誤 + 保存c2檔案錯誤 Error in Sound Input - 聲音輸入出錯誤 + 聲音輸入錯誤 Error in Sound Output - 聲音輸出錯誤 + 聲音輸錯誤 @@ -3784,7 +3784,7 @@ list. The list can be maintained in Settings (F2). Subprocess Error - 子流程出錯誤 + 子流程錯誤 @@ -3802,7 +3802,7 @@ list. The list can be maintained in Settings (F2). Subprocess error - 子進程出錯誤 + 子進程錯誤 @@ -3841,7 +3841,7 @@ list. The list can be maintained in Settings (F2). No data read from disk. Wrong file format? - 沒有從磁盤讀取數據. 檔案格式出錯誤? + 沒有從磁盤讀取數據. 檔案格式錯誤? @@ -3955,7 +3955,51 @@ list. The list can be maintained in Settings (F2). <tr><td><b>Alt+Z </b></td><td>Clear hung decoder status</td></tr> </table> Keyboard shortcuts help window contents - + <table cellspacing=1> + <tr><td><b>Esc </b></td><td>停止發送,中止通聯,清除下一個呼叫隊列</td></tr> + <tr><td><b>F1 </b></td><td>在線用戶指南 (Alt: 發射 Tx6)</td></tr> + <tr><td><b>Shift+F1 </b></td><td>版權聲明</td></tr> + <tr><td><b>Ctrl+F1 </b></td><td>關於 WSJT-X</td></tr> + <tr><td><b>F2 </b></td><td>打開設置窗口 (Alt: 發射 Tx2)</td></tr> + <tr><td><b>F3 </b></td><td>顯示鍵盤快捷鍵 (Alt: 發射 Tx3)</td></tr> + <tr><td><b>F4 </b></td><td>清除DX呼號, DX網格, 發射信息 1-4 (Alt: 發射 Tx4)</td></tr> + <tr><td><b>Alt+F4 </b></td><td>退出程序</td></tr> + <tr><td><b>F5 </b></td><td>顯示特殊鼠標命令 (Alt: transmit Tx5)</td></tr> + <tr><td><b>F6 </b></td><td>打開目錄中下一個文件 (Alt: toggle "Call 1st")</td></tr> + <tr><td><b>Shift+F6 </b></td><td>直接解碼所有剩餘檔</td></tr> + <tr><td><b>F7 </b></td><td>顯示信息平均視窗</td></tr> + <tr><td><b>F11 </b></td><td>將發射頻率向下移動 1 赫茲</td></tr> + <tr><td><b>Ctrl+F11 </b></td><td>移動相同的 接收 和 發射頻率向下移動 1 赫茲</td></tr> + <tr><td><b>Shift+F11 </b></td><td>將發射頻率向下移動 60 赫茲 (FT8) 或 90 赫茲 (FT4)</td></tr> + <tr><td><b>Ctrl+Shift+F11 </b></td><td>將頻率向下移動 2000 赫茲</td></tr> + <tr><td><b>F12 </b></td><td>將接收頻率向上移動 1 赫茲</td></tr> + <tr><td><b>Ctrl+F12 </b></td><td>相同的接收和發射頻率向上 1 赫茲</td></tr> + <tr><td><b>Shift+F12 </b></td><td>將發射頻率向上移動 60 赫茲(FT8) or 90 赫茲 (FT4)</td></tr> + <tr><td><b>Ctrl+Shift+F12 </b></td><td>將頻率調高 2000 赫茲</td></tr> + <tr><td><b>Alt+1-6 </b></td><td>現在將傳輸設置為選項卡 1 上的此號碼</td></tr> + <tr><td><b>Ctl+1-6 </b></td><td>在選項卡 1 上將下一個傳輸設置為此號碼</td></tr> + <tr><td><b>Alt+B </b></td><td>切換 "最佳 S+P" 狀態</td></tr> + <tr><td><b>Alt+C </b></td><td>切換 "呼叫 CQ 強制呼叫第 1" 複選框</td></tr> + <tr><td><b>Alt+D </b></td><td>在通聯頻率再次解碼</td></tr> + <tr><td><b>Shift+D </b></td><td>全部解碼(兩個視窗)</td></tr> + <tr><td><b>Ctrl+E </b></td><td>打開 TX even/1st</td></tr> + <tr><td><b>Shift+E </b></td><td>關閉 TX even/1st</td></tr> + <tr><td><b>Alt+E </b></td><td>擦除</td></tr> + <tr><td><b>Ctrl+F </b></td><td>編輯自訂義文字資訊</td></tr> + <tr><td><b>Alt+G </b></td><td>生成標準信息</td></tr> + <tr><td><b>Alt+H </b></td><td>停止發射</td></tr> + <tr><td><b>Ctrl+L </b></td><td>在資料庫中尋找呼號, 生成標準信息</td></tr> + <tr><td><b>Alt+M </b></td><td>監聽</td></tr> + <tr><td><b>Alt+N </b></td><td>啟用發射</td></tr> + <tr><td><b>Ctrl+O </b></td><td>打開 .wav 檔案</td></tr> + <tr><td><b>Alt+O </b></td><td>更換操作員</td></tr> + <tr><td><b>Alt+Q </b></td><td>記錄通聯</td></tr> + <tr><td><b>Ctrl+R </b></td><td>將 Tx4 訊息設定為 RRR(不在 FT4 中)</td></tr> + <tr><td><b>Alt+R </b></td><td>將 Tx4 消息設置為 RR73</td></tr> + <tr><td><b>Alt+S </b></td><td>停止監聽</td></tr> + <tr><td><b>Alt+T </b></td><td>切換調諧狀態</td></tr> + <tr><td><b>Alt+Z </b></td><td>清除掛起解碼器狀態</td></tr> +</table> @@ -3991,7 +4035,37 @@ list. The list can be maintained in Settings (F2). </tr> </table> Mouse commands help window contents - + <table cellpadding=5> + <tr> + <th align="right">點擊</th> + <th align="left">行動</th> + </tr> + <tr> + <td align="right">瀑布圖:</td> + <td><b>Click</b> 設置接收頻率.<br/> + <b>Shift-click</b> 設置發射頻率.<br/> + <b>Ctrl-click</b> or <b>右鍵單擊</b> 設置接收和發射頻率.<br/> + <b>Double-click</b> 在接收頻率解碼.<br/> + </td> + </tr> + <tr> + <td align="right">解碼文字:</td> + <td><b>Double-click</b> 解碼的文字將第二個呼號複製到 Dx 呼號,<br/> + 定位器到 Dx 網格,將接收和發射頻率更改為<br/> + 解碼信號的頻率, 並生成<br/> + 標準信息.<br/> + 如果 <b>保持發射頻率</b> 已選中或在消息中顯示第一個呼號<br/> + 是你自己的呼叫, 發射頻率不更改,除非 <br/> + <b>Ctrl</b> 鍵被按下.<br/> + </td> + </tr> + <tr> + <td align="right">擦除按鈕:</td> + <td><b>點擊</b> 擦除通聯視窗.<br/> + <b>按兩下</b> to erase QSO and Band Activity windows. + </td> + </tr> +</table> @@ -4341,7 +4415,7 @@ UDP 服務器 %2:%3 Unexpected rig error - 無線電設備意外出錯誤 + 無線電設備意外錯誤 @@ -4369,27 +4443,27 @@ UDP 服務器 %2:%3 Error reading waterfall palette file "%1:%2" too many colors. - 讀取瀑布調色板檔案時出錯誤 "%1:%2" 太多顏色. + 讀取瀑布調色板檔案時錯誤 "%1:%2" 太多顏色. Error reading waterfall palette file "%1:%2" invalid triplet. - 讀取瀑布調色板檔案時出錯誤 "%1:%2" 無效的三元組. + 讀取瀑布調色板檔案時錯誤 "%1:%2" 無效的三元組. Error reading waterfall palette file "%1:%2" invalid color. - 讀取瀑布調色板檔案時出錯誤 "%1:%2" 無效的顏色. + 讀取瀑布調色板檔案時錯誤 "%1:%2" 無效的顏色. Error opening waterfall palette file "%1": %2. - 讀取瀑布調色板檔案時出錯誤 "%1": %2. + 讀取瀑布調色板檔案時錯誤 "%1": %2. Error writing waterfall palette file "%1": %2. - 讀取瀑布調色板檔案時出錯誤 "%1": %2. + 讀取瀑布調色板檔案時錯誤 "%1": %2. @@ -4402,7 +4476,7 @@ UDP 服務器 %2:%3 File System Error - 檔案系統出錯誤 + 檔案系統錯誤 @@ -4413,7 +4487,7 @@ Error(%3): %4 無法重命名檔案: "%1" 到: "%2" -出錯誤(%3): %4 +錯誤(%3): %4 @@ -4453,7 +4527,7 @@ Error(%3): %4 Error(%2): %3 無法開啟檔案: "%1" -出錯誤(%2): %3 +錯誤(%2): %3 @@ -4469,7 +4543,7 @@ Error(%2): %3 Error(%2): %3 無法寫入檔案: "%1" -出錯誤(%2): %3 +錯誤(%2): %3 @@ -4508,7 +4582,7 @@ Error(%2): %3 Check this if you get SSL/TLS errors - 如果您收到SSL/TLS錯誤, 請選擇此項 + 如果您得到SSL/TLS錯誤, 請選擇此項 @@ -4526,12 +4600,12 @@ Error(%2): %3 An error opening the audio input device has occurred. - 開啟音頻輸入設備時出錯誤. + 開啟音頻輸入設備時錯誤. An error occurred during read from the audio input device. - 從音頻輸入設備讀取時出錯誤. + 從音頻輸入設備讀取時錯誤. @@ -4541,7 +4615,7 @@ Error(%2): %3 Non-recoverable error, audio input device not usable at this time. - 不可恢復的出錯誤, 音頻輸入設備此時不可用. + 不可恢復的錯誤, 音頻輸入設備此時不可用. @@ -4718,7 +4792,7 @@ Error(%2): %3 Unexpected rig error - 無線電設備意外出錯誤 + 無線電設備意外錯誤 @@ -4998,7 +5072,7 @@ Error(%2): %3 <html><head/><body><p>Type 2 compound callsigns are those with prefixes or suffixes not included in the allowed shortlist (See Help-&gt;Add-on prefixes and suffixes).</p><p>This option determines which generated messages should contain your full type 2 compound call sign rather than your base callsign. It only applies if you have a type 2 compound callsign.</p><p>This option controls the way the messages that are used to answer CQ calls are generated. Generated messages 6 (CQ) and 5 (73) will always contain your full callsign. The JT65 and JT9 protocols allow for some standard messages with your full call at the expense of another piece of information such as the DX call or your locator.</p><p>Choosing message 1 omits the DX callsign which may be an issue when replying to CQ calls. Choosing message 3 also omits the DX callsign and many versions of this and other software will not extract the report. Choosing neither means that your full callsign only goes in your message 5 (73) so your QSO partner may log the wrong callsign.</p><p>None of these options are perfect, message 3 is usually best but be aware your QSO partner may not log the report you send them.</p></body></html> - <html><head/><body><p>複合呼號類型2是那些前綴或後綴不包括在允許的決選名單中 (請參閱説明-& gt; 載入項目前綴和後綴).<p><p>這個選項確定哪些產生的資訊應包含完整類型2複合呼號, 而不是基本呼號.它僅適用於類型為2的複合呼號.</p><p>這個選項控制用於應答 CQ 呼叫的資訊產生方式.產生的資訊 6 (CQ) 和 5 (73) 將始終包含您的完整呼號.jt65 和 jt9 協定允許在您的完整呼叫中使用一些標準資訊, 而犧牲了另一條資訊, 如 DX 呼叫或您的定位.</p><p>選擇資訊1省略 DX 呼號, 這在答覆 CQ 呼叫時可能是一個問題.選擇資訊3也會省略 DX 呼號, 此軟體和其他軟體的許多版本都不會提取報告.選擇這兩個都意味著你的完整呼號只會出現在你的資訊 5 (73) 中, 所以你的通聯夥伴我的日誌是出錯誤的呼號.</p><p>這些選項都不是完美的, 資訊 3 是最好的, 但請注意, 您的通聯合作夥伴可能不會記錄您傳送的報告.</p></body></html> + <html><head/><body><p>複合呼號類型2是那些前綴或後綴不包括在允許的決選名單中 (請參閱説明-& gt; 載入項目前綴和後綴).<p><p>這個選項確定哪些產生的資訊應包含完整類型2複合呼號, 而不是基本呼號.它僅適用於類型為2的複合呼號.</p><p>這個選項控制用於應答 CQ 呼叫的資訊產生方式.產生的資訊 6 (CQ) 和 5 (73) 將始終包含您的完整呼號.jt65 和 jt9 協定允許在您的完整呼叫中使用一些標準資訊, 而犧牲了另一條資訊, 如 DX 呼叫或您的定位.</p><p>選擇資訊1省略 DX 呼號, 這在答覆 CQ 呼叫時可能是一個問題.選擇資訊3也會省略 DX 呼號, 此軟體和其他軟體的許多版本都不會提取報告.選擇這兩個都意味著你的完整呼號只會出現在你的資訊 5 (73) 中, 所以你的通聯夥伴我的日誌是錯誤的呼號.</p><p>這些選項都不是完美的, 資訊 3 是最好的, 但請注意, 您的通聯合作夥伴可能不會記錄您傳送的報告.</p></body></html> @@ -5531,7 +5605,7 @@ or bandwidth is selected). None - + From e52cd9fb14e7170cc7d179f3d4c0ba3f143ddef1 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 9 Nov 2020 12:56:32 +0000 Subject: [PATCH 50/73] Further Chinese and Hong Kong UI translations, tnx Sze-To, VR2UPU --- translations/wsjtx_zh.ts | 88 +++++++++----------- translations/wsjtx_zh_HK.ts | 158 +++++++++++++++++------------------- 2 files changed, 113 insertions(+), 133 deletions(-) diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index 5a9824c8d..e223501dc 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -3637,6 +3637,11 @@ list. The list can be maintained in Settings (F2). Reduce system load 降低系统负载 + + + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 + 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 + Error Scanning ADIF Log @@ -3838,6 +3843,15 @@ list. The list can be maintained in Settings (F2). The "fmt.all" file will be renamed as "fmt.bak" "fmt.all" 文件将重命名为 "fmt.bak" + + + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: + +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." + 如果您根据 GNU 通用公共许可证条款合理使用 WSJT-X 的任何部分, 则必须在衍生作品中醒目地显示以下版权声明: + +"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." + No data read from disk. Wrong file format? @@ -3893,20 +3907,6 @@ list. The list can be maintained in Settings (F2). Fox Mode warning 狐狸模式警告 - - - If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: - -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - 如果您根据 GNU 通用公共许可证条款合理使用 WSJT-X 的任何部分, 则必须在衍生作品中醒目地显示以下版权声明: - -"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." - - - - Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 - <table cellspacing=1> @@ -5388,11 +5388,6 @@ quiet period when decoding is done. Data bits 数据位元 - - - Data Bits - 数据位元 - D&efault @@ -5418,11 +5413,6 @@ quiet period when decoding is done. Stop bits 停止位元 - - - Stop Bits - 停止位元 - @@ -5791,6 +5781,11 @@ both here. 通道; 那么你通常会想要选择单声道或 双声道. + + + Enable VHF and submode features + 启用甚高频和子模式功能 + Ou&tput: @@ -5991,11 +5986,26 @@ and DX Grid fields when a 73 or free text message is sent. Network Services 网络服务 + + + <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> + <html><head/><body><p>该程序可以将你的电台详细信息和所有解码信号以网格发送到http://pskreporter.info网站.</p><p>这用于反向信标分析,这对于评估传播和系统性能非常有用.</p></body></html> + Enable &PSK Reporter Spotting 启用&PSK Reporter Spotting + + + <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> + <html><head/><body><p>如果需要可靠的连接, 请选择此选项</p><p>大多数用户不需要这个, 默认使用UDP, 效率更高. 只有当你有证据表明从你到PSK Reporter的UDP流量丢失时, 才选择这个.</p></body></html> + + + + Use TCP/IP connection + 使用TCP/IP连接 + UDP Server @@ -6163,36 +6173,11 @@ Right click for insert and delete options. <html><head/><body><p>Click to scan the wsjtx_log.adi ADIF file again for worked before information</p></body></html> <html><head/><body><p>单击以再次扫描wsjtx_log.adi ADIF文件,获取以前工作过的信息</p></body></html> - - - <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> - <html><head/><body><p>使用复选框启用或禁用项目,并右键单击项目以更改或取消设置前景颜色, 背景颜色, 或将项目重置为默认值. 拖放项目以更改其优先级, 列表中较高的优先级较高.</p><p>请注意, 每个前景或背景颜色都可以设置或取消设置, 取消设置意味着它未为该项分配, 其类型和低优先级项可能适用.</p></body></html> - Rescan ADIF Log 重新扫描 ADIF 日志 - - - Enable VHF and submode features - 启用甚高频和子模式功能 - - - - <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> - <html><head/><body><p>该程序可以将你的电台详细信息和所有解码信号以网格发送到http://pskreporter.info网站.</p><p>这用于反向信标分析,这对于评估传播和系统性能非常有用.</p></body></html> - - - - <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> - <html><head/><body><p>如果需要可靠的连接, 请选择此选项</p><p>大多数用户不需要这个, 默认使用UDP, 效率更高. 只有当你有证据表明从你到PSK Reporter的UDP流量丢失时, 才选择这个.</p></body></html> - - - - Use TCP/IP connection - 使用TCP/IP连接 - <html><head/><body><p>Push to reset all highlight items above to default values and priorities.</p></body></html> @@ -6203,6 +6188,11 @@ Right click for insert and delete options. Reset Highlighting 重置高亮显示 + + + <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> + <html><head/><body><p>使用复选框启用或禁用项目,并右键单击项目以更改或取消设置前景颜色, 背景颜色, 或将项目重置为默认值. 拖放项目以更改其优先级, 列表中较高的优先级较高.</p><p>请注意, 每个前景或背景颜色都可以设置或取消设置, 取消设置意味着它未为该项分配, 其类型和低优先级项可能适用.</p></body></html> + <html><head/><body><p>Check to indicate new DXCC entities, grid squares, and callsigns per mode.</p></body></html> diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index c8c25553b..35b7e60c5 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -3637,6 +3637,11 @@ list. The list can be maintained in Settings (F2). Reduce system load 降低系統負載 + + + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 + 樣品遺失過多 -%1 (%2 sec) 音效的畫面在週期開始時遺失 %3 + Error Scanning ADIF Log @@ -3838,6 +3843,15 @@ list. The list can be maintained in Settings (F2). The "fmt.all" file will be renamed as "fmt.bak" "fmt.all" 檔案將重新命名為 "fmt.bak" + + + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: + +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." + 如果您根據 GNU 通用公共授權條款合理使用 WSJT-X 的任何部分, 則必須在衍生作品中醒目地顯示以下版權聲明: + +"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." + No data read from disk. Wrong file format? @@ -3858,55 +3872,6 @@ list. The list can be maintained in Settings (F2). Keyboard Shortcuts 鍵盤快捷鍵 - - - Special Mouse Commands - 滑鼠特殊組合 - - - - No more files to open. - 沒有要打開的檔. - - - - Spotting to PSK Reporter unavailable - 無法發送至PSK Reporter - - - - Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. - 請選擇其他發射頻率. WSJT-X 不會故意傳輸另一個模式在 WSPR 30米子波段上. - - - - WSPR Guard Band - WSPR保護波段 - - - - Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. - 請選擇其他頻率. WSJT-X 不會運行狐狸模式在標準 FT8 波段. - - - - Fox Mode warning - 狐狸模式警告 - - - - If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: - -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - 如果您根據 GNU 通用公共授權條款合理使用 WSJT-X 的任何部分, 則必須在衍生作品中醒目地顯示以下版權聲明: - -"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." - - - - Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - 樣品遺失過多 -%1 (%2 sec) 音效的畫面在週期開始時遺失 %3 - <table cellspacing=1> @@ -4001,6 +3966,11 @@ list. The list can be maintained in Settings (F2). <tr><td><b>Alt+Z </b></td><td>清除掛起解碼器狀態</td></tr> </table> + + + Special Mouse Commands + 特殊滑鼠組合 + <table cellpadding=5> @@ -4067,6 +4037,36 @@ list. The list can be maintained in Settings (F2). </tr> </table> + + + No more files to open. + 沒有要打開的檔. + + + + Spotting to PSK Reporter unavailable + 無法發送至PSK Reporter + + + + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. + 請選擇其他發射頻率. WSJT-X 不會故意傳輸另一個模式在 WSPR 30米子波段上. + + + + WSPR Guard Band + WSPR保護波段 + + + + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. + 請選擇其他頻率. WSJT-X 不會運行狐狸模式在標準 FT8 波段. + + + + Fox Mode warning + 狐狸模式警告 + Last Tx: %1 @@ -5389,11 +5389,6 @@ quiet period when decoding is done. Data bits 數據位元 - - - Data Bits - 數據位元 - D&efault @@ -5419,11 +5414,6 @@ quiet period when decoding is done. Stop bits 停止位元 - - - Stop Bits - 停止位元 - @@ -5792,6 +5782,11 @@ both here. 通道; 那麼你通常會想要選擇單聲道或 雙聲道. + + + Enable VHF and submode features + 啟用甚高頻和子模式功能 + Ou&tput: @@ -5992,11 +5987,26 @@ and DX Grid fields when a 73 or free text message is sent. Network Services 網絡服務 + + + <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> + <html><head/><body><p>該程式可以將你的電臺詳細資訊和所有解碼信號以網格發送到http://pskreporter.info網站.</p><p>這用於反向信標分析,這對於評估傳播和系統性能非常有用.</p></body></html> + Enable &PSK Reporter Spotting 啟用&PSK Reporter Spotting + + + <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> + <html><head/><body><p>如果需要可靠的連接, 請選擇此選項</p><p>大多數使用者不需要這個, 預設使用UDP, 效率更高. 只有當你有證據表明從你到PSK Reporter的UDP流量丟失時, 才選擇這個.</p></body></html> + + + + Use TCP/IP connection + 使用TCP/IP連接 + UDP Server @@ -6164,36 +6174,11 @@ Right click for insert and delete options. <html><head/><body><p>Click to scan the wsjtx_log.adi ADIF file again for worked before information</p></body></html> <html><head/><body><p>按一下以再次掃描wsjtx_log.adi ADIF檔,獲取以前工作過的資訊</p></body></html> - - - <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> - <html><head/><body><p>使用複選框啟用或禁用專案, 並右鍵單擊專案以更改或取消設置前景顏色, 背景顏色, 或將專案重置為預設值. 拖放專案以更改其優先順序, 清單中較高的優先順序較高.</p><p> 請注意,每個前景或背景顏色都可以設置或取消設置, 未設置意味著未為該專案分配該類型, 低優先順序項可能適用.</p></body></html> - Rescan ADIF Log 重新掃描 ADIF 日誌 - - - Enable VHF and submode features - 啟用甚高頻和子模式功能 - - - - <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> - <html><head/><body><p>該程式可以將你的電臺詳細資訊和所有解碼信號以網格發送到http://pskreporter.info網站.</p><p>這用於反向信標分析,這對於評估傳播和系統性能非常有用.</p></body></html> - - - - <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> - <html><head/><body><p>如果需要可靠的連接, 請選擇此選項</p><p>大多數使用者不需要這個, 預設使用UDP, 效率更高. 只有當你有證據表明從你到PSK Reporter的UDP流量丟失時, 才選擇這個.</p></body></html> - - - - Use TCP/IP connection - 使用TCP/IP連接 - <html><head/><body><p>Push to reset all highlight items above to default values and priorities.</p></body></html> @@ -6204,6 +6189,11 @@ Right click for insert and delete options. Reset Highlighting 重置突顯顯示 + + + <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> + <html><head/><body><p>使用複選框啟用或禁用專案, 並右鍵單擊專案以更改或取消設置前景顏色, 背景顏色, 或將專案重置為預設值. 拖放專案以更改其優先順序, 清單中較高的優先順序較高.</p><p> 請注意,每個前景或背景顏色都可以設置或取消設置, 未設置意味著未為該專案分配該類型, 低優先順序項可能適用.</p></body></html> + <html><head/><body><p>Check to indicate new DXCC entities, grid squares, and callsigns per mode.</p></body></html> From f8965327706a449ce47b59845a87e485e34ab467 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 9 Nov 2020 12:56:32 +0000 Subject: [PATCH 51/73] Further Chinese and Hong Kong UI translations, tnx Sze-To, VR2UPU --- translations/wsjtx_zh.ts | 88 +++++++++----------- translations/wsjtx_zh_HK.ts | 158 +++++++++++++++++------------------- 2 files changed, 113 insertions(+), 133 deletions(-) diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index 5a9824c8d..e223501dc 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -3637,6 +3637,11 @@ list. The list can be maintained in Settings (F2). Reduce system load 降低系统负载 + + + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 + 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 + Error Scanning ADIF Log @@ -3838,6 +3843,15 @@ list. The list can be maintained in Settings (F2). The "fmt.all" file will be renamed as "fmt.bak" "fmt.all" 文件将重命名为 "fmt.bak" + + + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: + +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." + 如果您根据 GNU 通用公共许可证条款合理使用 WSJT-X 的任何部分, 则必须在衍生作品中醒目地显示以下版权声明: + +"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." + No data read from disk. Wrong file format? @@ -3893,20 +3907,6 @@ list. The list can be maintained in Settings (F2). Fox Mode warning 狐狸模式警告 - - - If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: - -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - 如果您根据 GNU 通用公共许可证条款合理使用 WSJT-X 的任何部分, 则必须在衍生作品中醒目地显示以下版权声明: - -"WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." - - - - Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 - <table cellspacing=1> @@ -5388,11 +5388,6 @@ quiet period when decoding is done. Data bits 数据位元 - - - Data Bits - 数据位元 - D&efault @@ -5418,11 +5413,6 @@ quiet period when decoding is done. Stop bits 停止位元 - - - Stop Bits - 停止位元 - @@ -5791,6 +5781,11 @@ both here. 通道; 那么你通常会想要选择单声道或 双声道. + + + Enable VHF and submode features + 启用甚高频和子模式功能 + Ou&tput: @@ -5991,11 +5986,26 @@ and DX Grid fields when a 73 or free text message is sent. Network Services 网络服务 + + + <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> + <html><head/><body><p>该程序可以将你的电台详细信息和所有解码信号以网格发送到http://pskreporter.info网站.</p><p>这用于反向信标分析,这对于评估传播和系统性能非常有用.</p></body></html> + Enable &PSK Reporter Spotting 启用&PSK Reporter Spotting + + + <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> + <html><head/><body><p>如果需要可靠的连接, 请选择此选项</p><p>大多数用户不需要这个, 默认使用UDP, 效率更高. 只有当你有证据表明从你到PSK Reporter的UDP流量丢失时, 才选择这个.</p></body></html> + + + + Use TCP/IP connection + 使用TCP/IP连接 + UDP Server @@ -6163,36 +6173,11 @@ Right click for insert and delete options. <html><head/><body><p>Click to scan the wsjtx_log.adi ADIF file again for worked before information</p></body></html> <html><head/><body><p>单击以再次扫描wsjtx_log.adi ADIF文件,获取以前工作过的信息</p></body></html> - - - <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> - <html><head/><body><p>使用复选框启用或禁用项目,并右键单击项目以更改或取消设置前景颜色, 背景颜色, 或将项目重置为默认值. 拖放项目以更改其优先级, 列表中较高的优先级较高.</p><p>请注意, 每个前景或背景颜色都可以设置或取消设置, 取消设置意味着它未为该项分配, 其类型和低优先级项可能适用.</p></body></html> - Rescan ADIF Log 重新扫描 ADIF 日志 - - - Enable VHF and submode features - 启用甚高频和子模式功能 - - - - <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> - <html><head/><body><p>该程序可以将你的电台详细信息和所有解码信号以网格发送到http://pskreporter.info网站.</p><p>这用于反向信标分析,这对于评估传播和系统性能非常有用.</p></body></html> - - - - <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> - <html><head/><body><p>如果需要可靠的连接, 请选择此选项</p><p>大多数用户不需要这个, 默认使用UDP, 效率更高. 只有当你有证据表明从你到PSK Reporter的UDP流量丢失时, 才选择这个.</p></body></html> - - - - Use TCP/IP connection - 使用TCP/IP连接 - <html><head/><body><p>Push to reset all highlight items above to default values and priorities.</p></body></html> @@ -6203,6 +6188,11 @@ Right click for insert and delete options. Reset Highlighting 重置高亮显示 + + + <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> + <html><head/><body><p>使用复选框启用或禁用项目,并右键单击项目以更改或取消设置前景颜色, 背景颜色, 或将项目重置为默认值. 拖放项目以更改其优先级, 列表中较高的优先级较高.</p><p>请注意, 每个前景或背景颜色都可以设置或取消设置, 取消设置意味着它未为该项分配, 其类型和低优先级项可能适用.</p></body></html> + <html><head/><body><p>Check to indicate new DXCC entities, grid squares, and callsigns per mode.</p></body></html> diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index c8c25553b..35b7e60c5 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -3637,6 +3637,11 @@ list. The list can be maintained in Settings (F2). Reduce system load 降低系統負載 + + + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 + 樣品遺失過多 -%1 (%2 sec) 音效的畫面在週期開始時遺失 %3 + Error Scanning ADIF Log @@ -3838,6 +3843,15 @@ list. The list can be maintained in Settings (F2). The "fmt.all" file will be renamed as "fmt.bak" "fmt.all" 檔案將重新命名為 "fmt.bak" + + + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: + +"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." + 如果您根據 GNU 通用公共授權條款合理使用 WSJT-X 的任何部分, 則必須在衍生作品中醒目地顯示以下版權聲明: + +"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." + No data read from disk. Wrong file format? @@ -3858,55 +3872,6 @@ list. The list can be maintained in Settings (F2). Keyboard Shortcuts 鍵盤快捷鍵 - - - Special Mouse Commands - 滑鼠特殊組合 - - - - No more files to open. - 沒有要打開的檔. - - - - Spotting to PSK Reporter unavailable - 無法發送至PSK Reporter - - - - Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. - 請選擇其他發射頻率. WSJT-X 不會故意傳輸另一個模式在 WSPR 30米子波段上. - - - - WSPR Guard Band - WSPR保護波段 - - - - Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. - 請選擇其他頻率. WSJT-X 不會運行狐狸模式在標準 FT8 波段. - - - - Fox Mode warning - 狐狸模式警告 - - - - If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: - -"The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - 如果您根據 GNU 通用公共授權條款合理使用 WSJT-X 的任何部分, 則必須在衍生作品中醒目地顯示以下版權聲明: - -"WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." - - - - Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - 樣品遺失過多 -%1 (%2 sec) 音效的畫面在週期開始時遺失 %3 - <table cellspacing=1> @@ -4001,6 +3966,11 @@ list. The list can be maintained in Settings (F2). <tr><td><b>Alt+Z </b></td><td>清除掛起解碼器狀態</td></tr> </table> + + + Special Mouse Commands + 特殊滑鼠組合 + <table cellpadding=5> @@ -4067,6 +4037,36 @@ list. The list can be maintained in Settings (F2). </tr> </table> + + + No more files to open. + 沒有要打開的檔. + + + + Spotting to PSK Reporter unavailable + 無法發送至PSK Reporter + + + + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. + 請選擇其他發射頻率. WSJT-X 不會故意傳輸另一個模式在 WSPR 30米子波段上. + + + + WSPR Guard Band + WSPR保護波段 + + + + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. + 請選擇其他頻率. WSJT-X 不會運行狐狸模式在標準 FT8 波段. + + + + Fox Mode warning + 狐狸模式警告 + Last Tx: %1 @@ -5389,11 +5389,6 @@ quiet period when decoding is done. Data bits 數據位元 - - - Data Bits - 數據位元 - D&efault @@ -5419,11 +5414,6 @@ quiet period when decoding is done. Stop bits 停止位元 - - - Stop Bits - 停止位元 - @@ -5792,6 +5782,11 @@ both here. 通道; 那麼你通常會想要選擇單聲道或 雙聲道. + + + Enable VHF and submode features + 啟用甚高頻和子模式功能 + Ou&tput: @@ -5992,11 +5987,26 @@ and DX Grid fields when a 73 or free text message is sent. Network Services 網絡服務 + + + <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> + <html><head/><body><p>該程式可以將你的電臺詳細資訊和所有解碼信號以網格發送到http://pskreporter.info網站.</p><p>這用於反向信標分析,這對於評估傳播和系統性能非常有用.</p></body></html> + Enable &PSK Reporter Spotting 啟用&PSK Reporter Spotting + + + <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> + <html><head/><body><p>如果需要可靠的連接, 請選擇此選項</p><p>大多數使用者不需要這個, 預設使用UDP, 效率更高. 只有當你有證據表明從你到PSK Reporter的UDP流量丟失時, 才選擇這個.</p></body></html> + + + + Use TCP/IP connection + 使用TCP/IP連接 + UDP Server @@ -6164,36 +6174,11 @@ Right click for insert and delete options. <html><head/><body><p>Click to scan the wsjtx_log.adi ADIF file again for worked before information</p></body></html> <html><head/><body><p>按一下以再次掃描wsjtx_log.adi ADIF檔,獲取以前工作過的資訊</p></body></html> - - - <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> - <html><head/><body><p>使用複選框啟用或禁用專案, 並右鍵單擊專案以更改或取消設置前景顏色, 背景顏色, 或將專案重置為預設值. 拖放專案以更改其優先順序, 清單中較高的優先順序較高.</p><p> 請注意,每個前景或背景顏色都可以設置或取消設置, 未設置意味著未為該專案分配該類型, 低優先順序項可能適用.</p></body></html> - Rescan ADIF Log 重新掃描 ADIF 日誌 - - - Enable VHF and submode features - 啟用甚高頻和子模式功能 - - - - <html><head/><body><p>The program can send your station details and all decoded signals with grid squares as spots to the http://pskreporter.info web site.</p><p>This is used for reverse beacon analysis which is very useful for assessing propagation and system performance.</p></body></html> - <html><head/><body><p>該程式可以將你的電臺詳細資訊和所有解碼信號以網格發送到http://pskreporter.info網站.</p><p>這用於反向信標分析,這對於評估傳播和系統性能非常有用.</p></body></html> - - - - <html><head/><body><p>Check this option if a reliable connection is needed</p><p>Most users do not need this, the default uses UDP which is more efficient. Only check this if you have evidence that UDP traffic from you to PSK Reporter is being lost.</p></body></html> - <html><head/><body><p>如果需要可靠的連接, 請選擇此選項</p><p>大多數使用者不需要這個, 預設使用UDP, 效率更高. 只有當你有證據表明從你到PSK Reporter的UDP流量丟失時, 才選擇這個.</p></body></html> - - - - Use TCP/IP connection - 使用TCP/IP連接 - <html><head/><body><p>Push to reset all highlight items above to default values and priorities.</p></body></html> @@ -6204,6 +6189,11 @@ Right click for insert and delete options. Reset Highlighting 重置突顯顯示 + + + <html><head/><body><p>Enable or disable using the check boxes and right-click an item to change or unset the foreground color, background color, or reset the item to default values. Drag and drop the items to change their priority, higher in the list is higher in priority.</p><p>Note that each foreground or background color may be either set or unset, unset means that it is not allocated for that item's type and lower priority items may apply.</p></body></html> + <html><head/><body><p>使用複選框啟用或禁用專案, 並右鍵單擊專案以更改或取消設置前景顏色, 背景顏色, 或將專案重置為預設值. 拖放專案以更改其優先順序, 清單中較高的優先順序較高.</p><p> 請注意,每個前景或背景顏色都可以設置或取消設置, 未設置意味著未為該專案分配該類型, 低優先順序項可能適用.</p></body></html> + <html><head/><body><p>Check to indicate new DXCC entities, grid squares, and callsigns per mode.</p></body></html> From 9e71d070752c8fd4c17fb8684465e2ccc73fb90d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 9 Nov 2020 13:27:21 +0000 Subject: [PATCH 52/73] L10n translation file updates --- translations/wsjtx_ca.ts | 1315 +++++++++++++++++----------------- translations/wsjtx_da.ts | 1315 +++++++++++++++++----------------- translations/wsjtx_en.ts | 1317 +++++++++++++++++----------------- translations/wsjtx_en_GB.ts | 1317 +++++++++++++++++----------------- translations/wsjtx_es.ts | 1312 +++++++++++++++++----------------- translations/wsjtx_it.ts | 1315 +++++++++++++++++----------------- translations/wsjtx_ja.ts | 1315 +++++++++++++++++----------------- translations/wsjtx_zh.ts | 1325 ++++++++++++++++++----------------- translations/wsjtx_zh_HK.ts | 1325 ++++++++++++++++++----------------- 9 files changed, 6044 insertions(+), 5812 deletions(-) diff --git a/translations/wsjtx_ca.ts b/translations/wsjtx_ca.ts index 9aa47b5ac..e8e99b115 100644 --- a/translations/wsjtx_ca.ts +++ b/translations/wsjtx_ca.ts @@ -377,75 +377,75 @@ Configuration::impl - - - + + + &Delete &Esborrar - - + + &Insert ... &Insereix ... - + Failed to create save directory No s'ha pogut crear el directori per desar - + path: "%1% ruta: "%1% - + Failed to create samples directory No s'ha pogut crear el directori d'exemples - + path: "%1" ruta: "%1" - + &Load ... &Carrega ... - + &Save as ... &Guardar com ... - + &Merge ... &Combinar ... - + &Reset &Restablir - + Serial Port: Port sèrie: - + Serial port used for CAT control Port sèrie utilitzat per al control CAT - + Network Server: Servidor de xarxa: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -460,12 +460,12 @@ Formats: [adreça IPv6]:port - + USB Device: Dispositiu USB: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -476,8 +476,8 @@ Format: [VID[:PID[:VENDOR[:PRODUCT]]]] - - + + Invalid audio input device El dispositiu d'entrada d'àudio no és vàlid @@ -486,150 +486,156 @@ Format: El dispositiu de sortida d'àudio no és vàlid - + Invalid audio output device El dispositiu de sortida d'àudio no és vàlid - + Invalid PTT method El mètode de PTT no és vàlid - + Invalid PTT port El port del PTT no és vàlid - - + + Invalid Contest Exchange Intercanvi de concurs no vàlid - + You must input a valid ARRL Field Day exchange Has d’introduir un intercanvi de Field Day de l'ARRL vàlid - + You must input a valid ARRL RTTY Roundup exchange Has d’introduir un intercanvi vàlid de l'ARRL RTTY Roundup - + Reset Decode Highlighting Restableix Ressaltat de Descodificació - + Reset all decode highlighting and priorities to default values Restableix tot el ressaltat i les prioritats de descodificació als valors predeterminats - + WSJT-X Decoded Text Font Chooser Tipus de text de pantalla de descodificació WSJT-X - + Load Working Frequencies Càrrega les freqüències de treball - - - + + + Frequency files (*.qrg);;All files (*.*) Arxius de freqüència (*.qrg);;Tots els arxius (*.*) - + Replace Working Frequencies Substitueix les freqüències de treball - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? Segur que vols descartar les teves freqüències actuals de treball i reemplaçar-les per les carregades ? - + Merge Working Frequencies Combina les freqüències de treball - - - + + + Not a valid frequencies file L'arxiu de freqüències no és vàlid - + Incorrect file magic L'arxiu màgic es incorrecte - + Version is too new La versió és massa nova - + Contents corrupt Continguts corruptes - + Save Working Frequencies Desa les freqüències de treball - + Only Save Selected Working Frequencies Desa només les freqüències de treball seleccionades - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. Estàs segur que vols desar només les freqüències de treball seleccionades actualment? Fes clic a No per desar-ho tot. - + Reset Working Frequencies Restablir les freqüències de treball - + Are you sure you want to discard your current working frequencies and replace them with default ones? Segur que vols descartar les teves freqüències actuals de treball i reemplaçar-les per altres? - + Save Directory Directori de Guardar - + AzEl Directory Directori AzEl - + Rig control error Error de control de l'equip - + Failed to open connection to rig No s'ha pogut obrir la connexió al equip - + Rig failure Fallada en l'equip + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1452,22 +1458,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency Afedueix Freqüència - + IARU &Region: Regió &IARU: - + &Mode: &Mode: - + &Frequency (MHz): &Freqüència en MHz.: @@ -1589,180 +1595,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Error d'inicialització de Hamlib - + Hamlib settings file error: %1 at character offset %2 Error de l'arxiu de configuració de Hamlib: %1 en el desplaçament de caràcters %2 - + Hamlib settings file error: top level must be a JSON object Error de l'arxiu de configuració de Hamlib: el nivell superior ha de ser un objecte JSON - + Hamlib settings file error: config must be a JSON object Error de l'arxiu de configuració de Hamlib: config ha de ser un objecte JSON - + Unsupported CAT type Tipus CAT no admès - + Hamlib error: %1 while %2 Error de Hamlib: %1 mentre %2 - + opening connection to rig connexió d'obertura a l'equip - + getting current frequency obtenir la freqüència actual - + getting current mode obtenir el mode actual - - + + exchanging VFOs intercanviant VFOs - - + + getting other VFO frequency obtenint una altra freqüència de VFO - + getting other VFO mode obtenint un altre mode VFO - - + + setting current VFO ajustar el VFO actual - + getting frequency obtenint la freqüència - + getting mode obtenint el mode - - - + + + getting current VFO obtenir VFO actual - - - - + + + + getting current VFO frequency obtenir la freqüència actual del VFO - - - - - - + + + + + + setting frequency ajust de freqüència - - - - + + + + getting current VFO mode obtenir el mode VFO actual - - - - - + + + + + setting current VFO mode ajust del mode VFO actual - - + + setting/unsetting split mode ajustar/desajustar mode dividid (split) - - + + setting split mode ajustar mode dividid (Split) - + setting split TX frequency and mode ajust de freqüència i mode de transmissió dividida (Split) - + setting split TX frequency ajust de freqüència dividida (Split) en TX - + getting split TX VFO mode obtenir el mode dividit (Split) en TX del VFO - + setting split TX VFO mode ajustar del mode dividid (Split) en TX del VFO - + getting PTT state obtenir l'estat del PTT - + setting PTT on activant el PTT - + setting PTT off desactivant el PTT - + setting a configuration item establir un element de configuració - + getting a configuration item obtenir un element de configuració @@ -2085,196 +2091,196 @@ Error(%2): %3 WSJT-X de K1JT - - - - - - - - + + + + + + + + Band Activity Activitat a la banda - - + + UTC dB DT Freq Dr UTC dB DH Freq Dr - - - - - - - + + + + + + + Rx Frequency Freqüència de RX - + CQ only només CQ - + Enter this QSO in log Introdueix aquest QSO al log - + Log &QSO Log &QSO - + Stop monitoring Atura la monitorització - + &Stop &Aturar - + Toggle monitoring On/Off Activació / desactivació del control de monitorització - + &Monitor &Monitor - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>Esborra la finestra dreta, fes doble clic per esborrar les dues finestres.</p></body></html> - + Erase right window. Double-click to erase both windows. Esborra la finestra dreta, fes doble clic per esborrar les dues finestres. - + &Erase &Esborrar - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body><p>Neteja la mitjana de missatges acumulats.</p></body></html> - + Clear the accumulating message average. Neteja la mitjana de missatges acumulats. - + Clear Avg Esborra mitjana - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body><p>Descodificar el període de RX més recent en la freqüència de QSO</p></body></html> - + Decode most recent Rx period at QSO Frequency Descodificar el període de RX més recent en la freqüència de QSO - + &Decode &Descodificar - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body><p>Activar/Desactivar TX</p></body></html> - + Toggle Auto-Tx On/Off Activar/Desactivar TX - + E&nable Tx A&ctivar TX - + Stop transmitting immediately Deixa de transmetre immediatament - + &Halt Tx Aturar &TX - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>Activa/Desactiva el to de TX pur per a sintonització</p></body></html> - + Toggle a pure Tx tone On/Off Activa/Desactiva el to TX pur per a sintonització - + &Tune &Sintonitzar - + Menus Menús - + Percentage of minute sequences devoted to transmitting. Percentatge de seqüències de minuts dedicades a transmetre. - + Prefer Type 1 messages Preferiu els missatges de tipus 1 - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>Transmetre durant la següent seqüència.</p></body></html> - + USB dial frequency freqüència de dial USB - + 14.078 000 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body><p>30dB recomanat quan només hi ha soroll,<br/>en Verd és un bon nivell,<br/>en Vermell és poden produir retalls, i<br/>en Groc quan és massa baix.</p></body></html> - + Rx Signal Senyal de RX - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2285,344 +2291,344 @@ en Vermell és poden produir retalls i en Groc quan és massa baix - + DX Call Indicatiu DX - + DX Grid Locator DX - + Callsign of station to be worked Indiatiu de l'estació per ser treballada - + Search for callsign in database Buscar el indicatiu a la base de dades - + &Lookup &Cercar - + Locator of station to be worked Locator de l'estació a treballar - + Az: 251 16553 km Az: 251 16553 km - + Add callsign and locator to database Afegir indicatiu i locator a la base de dades - + Add Afegir - + Pwr Potència - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body><p>Si hi ha hagut un error en el control de l'equip, fes clic per restablir i llegir la freqüència del dial. S implica mode dividit o split.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. Si hi ha hagut un error en el control de l'equip, fes clic per restablir i llegir la freqüència del dial. S implica mode dividit o split. - + ? ? - + Adjust Tx audio level Ajust del nivell d'àudio de TX - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body><p>Selecciona la banda operativa, introdueix la freqüència en MHz o introdueix un increment de kHz seguit de k.</p></body></html> - + Frequency entry Freqüència d'entrada - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. Selecciona la banda operativa, introdueix la freqüència en MHz o introdueix un increment de kHz seguit de k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body><p>Marca per que es mantingui la freqüència de TX fixada quan facis doble clic sobre un text descodificat.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. Marca per que es mantingui la freqüència de TX fixada quan facis doble clic sobre un text descodificat. - + Hold Tx Freq Manté TX Freq - + Audio Rx frequency Freqüència d'Àudio en RX - - - - - + + + + + Hz Hz - - + + Rx RX - - + + Set Tx frequency to Rx Frequency Estableix la freqüència de RX en la de TX - + - + Frequency tolerance (Hz) Freqüència de Tolerància (Hz) - - + + F Tol F Tol - - + + Set Rx frequency to Tx Frequency Estableix la freqüència de TX en la de RX - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body><p>Sincronització del llindar. Els nombres més baixos accepten senyals de sincronització més febles.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. Sincronització del llindar. Els nombres més baixos accepten senyals de sincronització més febles. - + Sync Sinc - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>Marcar per utilitzar missatges de format curt.</p></body></html> - + Check to use short-format messages. Marcar per utilitzar missatges de format curt. - + Sh Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>Comprova que actives els modes ràpids JT9</p></body></html> - + Check to enable JT9 fast modes Comprova que actives els modes ràpids JT9 - - + + Fast Ràpid - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body><p>Activa la seqüència automàtica dels missatges de TX en funció dels missatges rebuts.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. Activa la seqüència automàtica dels missatges de TX en funció dels missatges rebuts. - + Auto Seq Seqüència Automàtica - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body><p>Contesta al primer CQ descodificat.</p></body></html> - + Check to call the first decoded responder to my CQ. Contesta al primer CQ descodificat. - + Call 1st Contesta al primer CQ - + Check to generate "@1250 (SEND MSGS)" in Tx6. Marca per generar "@1250 (SEND MSGS)" a TX6. - + Tx6 TX6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body><p>Marca a TX en minuts o seqüències de números parells, a partir de 0; desmarca les seqüències senars.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. Marca a TX en minuts o seqüències de números parells, a partir de 0; desmarca les seqüències senars. - + Tx even/1st Alternar període TX Parell/Senar - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body><p>Freqüència per cridar CQ en kHz per sobre dels MHz actuals</p></body></html> - + Frequency to call CQ on in kHz above the current MHz Freqüència per cridar CQ en kHz per sobre dels MHz actuals - + Tx CQ TX CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body><p>Marca això per trucar a CQ a la freqüència &quot;TX CQ&quot;. RX serà a la freqüència actual i el missatge CQ inclourà la freqüència de RX actual perquè els corresponsals sàpiguen a quina freqüència respondre.</p><p>No està disponible per als titulars de indicatiu no estàndard.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. Marca això per trucar a CQ a la freqüència "TX CQ". RX serà a la freqüència actual i el missatge CQ inclourà la freqüència de RX actual perquè els corresponsals sàpiguen a quina freqüència respondre. No està disponible per als titulars de indicatiu no estàndard. - + Rx All Freqs RX a totes les freqüències - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body><p>La submode determina l'espai entre tons; A és més estret.</p></body></html> - + Submode determines tone spacing; A is narrowest. La submode determina l'espai entre tons; A és més estret. - + Submode Submode - - + + Fox Fox - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>Marca per monitoritzar els missatges Sh.</p></body></html> - + Check to monitor Sh messages. Marca per monitoritzar els missatges Sh. - + SWL SWL - + Best S+P El millor S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body><p>Marca per començar a enregistrar dades de calibració.<br/>Mentre es mesura la correcció de calibratge, es desactiva.<br/>Si no està marcat, pots veure els resultats de la calibració.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2631,206 +2637,216 @@ Mentre es mesura la correcció de calibratge, es desactiva. Si no està marcat, pots veure els resultats de la calibració. - + Measure Mesura - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body><p>Informe de senyal: Relació senyal/soroll en amplada de banda de referència de 2500 Hz (dB).</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). Informe de senyal: Relació senyal/soroll en amplada de banda de referència de 2500 Hz (dB). - + Report Informe de senyal - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>TX/RX o Longitud de la seqüència de calibratge de la freqüència</p></body></html> - + Tx/Rx or Frequency calibration sequence length TX/RX o Longitud de la seqüència de calibratge de la freqüència - - + + s s - - + + T/R T/R - + Toggle Tx mode Commuta el mode TX - + Tx JT9 @ TX JT9 @ - + Audio Tx frequency Freqüència d'àudio de TX - - + + Tx TX - + Tx# TX# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body><p>Fes doble clic sobre un altre estació per posar a la cua en la trucada per al teu proper QSO.</p></body></html> - + + F High + + + + + F Low + + + + Double-click on another caller to queue that call for your next QSO. Fes doble clic sobre un altre estació per posar a la cua en la trucada per al teu proper QSO. - + Next Call Proper Indicatiu - + 1 1 - - - + + + Send this message in next Tx interval Envia aquest missatge al següent interval de TX - + Ctrl+2 Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>Envia aquest missatge al següent interval de TX.</p><p>Fes doble clic per canviar l’ús del missatge TX1 per iniciar un QSO amb una estació (no està permès per a titulars de indicatius compostos de tipus 1).</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Envia aquest missatge al següent interval de TX. Fes doble clic per canviar l’ús del missatge TX1 per iniciar un QSO amb una estació (no està permès per a titulars de indicatius compostos de tipus 1) - + Ctrl+1 Ctrl+1 - - - - + + + + Switch to this Tx message NOW Canvia a aquest missatge de TX ARA - + Tx &2 TX &2 - + Alt+2 Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>Canvia a aquest missatge de TX ARA.</p><p>Fes doble clic per canviar l’ús del missatge TX1 per iniciar un QSO amb una estació (no està permès per a titulars de indicatius compostos de tipus 1).</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Canvia a aquest missatge de TX ARA. Fes doble clic per canviar l’ús del missatge TX1 per iniciar un QSO amb una estació (no està permès per a titulars de indicatius compostos de tipus 1) - + Tx &1 TX &1 - + Alt+1 Alt+1 - + Ctrl+6 Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Envia aquest missatge al següent interval de TX.</p><p>Fes doble clic per restablir el missatge estàndard 73.</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message Envia aquest missatge al següent interval de TX. Fes doble clic per restablir el missatge estàndard 73 - + Ctrl+5 Ctrl+5 - + Ctrl+3 Ctrl+3 - + Tx &3 TX &3 - + Alt+3 Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>Envia aquest missatge al següent interval de TX.</p><p>Fes doble clic per alternar entre els missatges RRR i RR73 a TX4 (no està permès per a titulars d'indicatius compostos del tipus 2)</p><p>Els missatges RR73 només s’han d’utilitzar quan teniu una confiança raonable que no caldrà repetir cap missatge.</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2839,17 +2855,17 @@ Fes doble clic per alternar entre els missatges RRR i RR73 a TX4 (no està perm Els missatges RR73 només s’han d’utilitzar quan teniu una confiança raonable que no caldrà repetir cap missatge - + Ctrl+4 Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>Canvia a aquest missatge de TX ARA.</p><p>Fes doble clic per alternar entre els missatges RRR i RR73 a TX4 (no està permès per a titulars d'indicatius compostos del tipus 2)</p><p>Els missatges RR73 només s’han d’utilitzar quan teniu una confiança raonable que no caldrà repetir cap missatge.</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2858,64 +2874,64 @@ Fes doble clic per alternar entre els missatges RRR i RR73 a TX4 (no està perm Els missatges RR73 només s’han d’utilitzar quan teniu una confiança raonable que no caldrà repetir cap missatge - + Tx &4 TX &4 - + Alt+4 Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Canvia a aquest missatge de TX ARA.</p><p>Fes doble clic per restablir el missatge estàndard 73.</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message Canvia a aquest missatge de TX ARA. Fes doble clic per restablir el missatge estàndard 73 - + Tx &5 TX &5 - + Alt+5 Alt+5 - + Now Ara - + Generate standard messages for minimal QSO Genera missatges estàndard per a un QSO mínim - + Generate Std Msgs Generar Std Msgs - + Tx &6 TX &6 - + Alt+6 Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2926,25 +2942,35 @@ Prem ENTER per afegir el text actual a la llista predefinida La llista es pot mantenir a la configuració (F2). - + Queue up the next Tx message Posa a la cua el següent missatge de TX - + Next Pròxim - + 2 2 - + FST4W FST4W + + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + Calling CQ Cridant a CQ @@ -2954,8 +2980,8 @@ La llista es pot mantenir a la configuració (F2). Genera un missatge CQ - - + + CQ CQ @@ -2984,7 +3010,7 @@ La llista es pot mantenir a la configuració (F2). Generar un missatge per respondre a un CQ - + Grid Locator @@ -3025,138 +3051,138 @@ La llista es pot mantenir a la configuració (F2). 3 - + Max dB Màx dB - + CQ AF CQ AF - + CQ AN CQ AN - + CQ AS CA AS - + CQ EU CQ EU - + CQ NA CQ NA - + CQ OC CQ OC - + CQ SA CQ SA - + CQ 0 CQ 0 - + CQ 1 CQ 1 - + CQ 2 CQ 2 - + CQ 3 CQ 3 - + CQ 4 CQ 3 - + CQ 5 CQ 4 - + CQ 6 CQ 6 - + CQ 7 CQ 7 - + CQ 8 CQ 8 - + CQ 9 CQ 9 - + Reset Restablir - + N List N List - + N Slots N Slots - - - - - - - + + + + + + + Random a l’atzar - + Call Indicatiu - + S/N (dB) S/N (dB) - + Distance Distància - + More CQs Més CQ's @@ -3165,158 +3191,158 @@ La llista es pot mantenir a la configuració (F2). Percentatge de seqüències de 2 minuts dedicades a la transmissió. - - + + % % - + Tx Pct TX Pct - + Band Hopping Salt de Banda - + Choose bands and times of day for band-hopping. Tria bandes i hores del dia per al salt de bandes. - + Schedule ... Programació ... - + 1/2 1/2 - + 2/2 2/2 - + 1/3 1/3 - + 2/3 2/3 - + 3/3 3/3 - + 1/4 1/4 - + 2/4 2/4 - + 3/4 3/4 - + 4/4 4/4 - + 1/5 1/5 - + 2/5 2/5 - + 3/5 3/5 - + 4/5 4/5 - + 5/5 5/5 - + 1/6 1/6 - + 2/6 2/6 - + 3/6 3/6 - + 4/6 4/6 - + 5/6 5/6 - + 6/6 6/6 - + Upload decoded messages to WSPRnet.org. Carrega missatges descodificats a WSPRnet.org. - + Upload spots Carrega Spots - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>Els locator de 6 dígits fan que s’enviïn 2 missatges diferents, el segon conté el locator complet, però només un indicatiu trossejat, les altres estacions han d’haver descodificat el primer una vegada abans de poder descodificar el segon. Marca aquesta opció per enviar només locators de 4 dígits i s’evitarà el protocol de dos missatges.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. Els locator de 6 dígits fan que s’enviïn 2 missatges diferents, el segon conté el locator complet, però només un indicatiu trossejat, les altres estacions han d’haver descodificat el primer una vegada abans de poder descodificar el segon. Marca aquesta opció per enviar només locators de 4 dígits i s’evitarà el protocol de dos missatges. - + Quick-Start Guide to FST4 and FST4W Guia d'inici ràpid de FST4 i FST4W - + FST4 FST4 @@ -3329,7 +3355,7 @@ La llista es pot mantenir a la configuració (F2). Prefereixes missatges de tipus 1 - + No own call decodes No es descodifica cap indicatiu pròpi @@ -3338,62 +3364,62 @@ La llista es pot mantenir a la configuració (F2). Transmetre durant la següent seqüència de 2 minuts. - + Tx Next Proper TX - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. Configura la potència de TX en dBm (dB per sobre d'1 mW) com a part del vostre missatge WSPR. - + NB NB - + File Arxiu - + View Veure - + Decode Descodificar - + Save Guardar - + Help Ajuda - + Mode Mode - + Configurations Configuracions - + Tools Eines - + Exit Sortir @@ -3406,87 +3432,87 @@ La llista es pot mantenir a la configuració (F2). F2 - + About WSJT-X Quant a WSJT-X - + Waterfall Cascada - + Open Obrir - + Ctrl+O Ctrl+O - + Open next in directory Obre el següent directori - + Decode remaining files in directory Descodificar els arxius restants al directori - + Shift+F6 Maj.+F6 - + Delete all *.wav && *.c2 files in SaveDir Esborrar tots els arxius *.wav i *.c2 - + None Cap - + Save all Guardar-ho tot - + Online User Guide Guia d'usuari online - + Keyboard shortcuts Dreceres de teclat - + Special mouse commands Ordres especials del ratolí - + JT9 JT9 - + Save decoded Guarda el descodificat - + Normal Normal - + Deep Profunda @@ -3495,12 +3521,12 @@ La llista es pot mantenir a la configuració (F2). Monitor apagat a l’inici - + Erase ALL.TXT Esborrar l'arxiu ALL.TXT - + Erase wsjtx_log.adi Esborrar l'arxiu wsjtx_log.adi @@ -3533,7 +3559,7 @@ La llista es pot mantenir a la configuració (F2). Fes doble clic als conjunts d'indicatius d'activar TX - + F7 F7 @@ -3542,7 +3568,7 @@ La llista es pot mantenir a la configuració (F2). TX desactivat després d’enviar 73 - + Runaway Tx watchdog Seguretat de TX @@ -3555,12 +3581,12 @@ La llista es pot mantenir a la configuració (F2). TX freq bloquejat a RX freq - + JT65 JT65 - + JT9+JT65 JT9+JT65 @@ -3577,147 +3603,147 @@ La llista es pot mantenir a la configuració (F2). Mostra l'entitat DXCC i l'estat de B4 treballat - + Astronomical data Dades astronòmiques - + List of Type 1 prefixes and suffixes Llista de prefixos i sufixos de tipus 1 - + Settings... Configuració... - + Local User Guide Guia d'usuari local - + Open log directory Obre el directori del log - + JT4 JT4 - + Message averaging Mitjana de missatges - + Enable averaging Activa la mitjana - + Enable deep search Activa la cerca profunda - + WSPR WSPR - + Echo Graph Gràfic d'Eco - + F8 F8 - + Echo Eco - + EME Echo mode Mode EME Eco - + ISCAT ISCAT - + Fast Graph Gràfic ràpid - + F9 F9 - + &Download Samples ... &Descarrega mostres ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>Descarrega els arxius d’àudio d’exemple mostrant els diversos modes.</p></body></html> - + MSK144 MSK144 - + QRA64 QRA64 - + Release Notes Notes de llançament - + Enable AP for DX Call Habilita AP per al indicatiu de DX - + FreqCal FreqCal - + Measure reference spectrum Mesura l’espectre de referència - + Measure phase response Mesura la resposta en fase - + Erase reference spectrum Esborra l'espectre de referència - + Execute frequency calibration cycle Executa el cicle de calibració de freqüència - + Equalization tools ... Eines d'equalització ... @@ -3730,48 +3756,48 @@ La llista es pot mantenir a la configuració (F2). Mode experimental LF/MF - + FT8 FT8 - - + + Enable AP Activa AP - + Solve for calibration parameters Resol els paràmetres de calibratge - + Copyright notice Avís de drets d’autor - + Shift+F1 Maj.+F1 - + Fox log Log Fox - + FT8 DXpedition Mode User Guide Guia de l'usuari del mode DXpedition a FT8 - + Reset Cabrillo log ... Restableix el log de Cabrillo ... - + Color highlighting scheme Esquema de ressaltar el color @@ -3780,7 +3806,7 @@ La llista es pot mantenir a la configuració (F2). Log de Concurs - + Export Cabrillo log ... Exporta el log de Cabrillo ... @@ -3789,49 +3815,49 @@ La llista es pot mantenir a la configuració (F2). Guia d'inici ràpid a WSJT-X 2.0 - + Contest log Log de Concurs - + Erase WSPR hashtable Esborra la taula WSPR - + FT4 FT4 - + Rig Control Error Error del control del equip - - - + + + Receiving Rebent - + Do you want to reconfigure the radio interface? Vols reconfigurar la interfície de la ràdio ? - + %1 (%2 sec) audio frames dropped %1 (%2 sec) s’han caigut els marcs d’àudio - + Audio Source Font d'àudio - + Reduce system load Reduir la càrrega del sistema @@ -3840,194 +3866,194 @@ La llista es pot mantenir a la configuració (F2). Mostres caigudes excessives - %1 (%2 sec) s’han caigut els marcs d’àudio - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Error Scanning ADIF Log Error d'escaneig del log ADIF - + Scanned ADIF log, %1 worked before records created Log ADIF escanejat, %1 funcionava abans de la creació de registres - + Error Loading LotW Users Data S'ha produït un error al carregar les dades dels usuaris de LotW - + Error Writing WAV File S'ha produït un error al escriure l'arxiu WAV - + Enumerating audio devices - + Configurations... Configuracions... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message Missatge - + Error Killing jt9.exe Process Error en matar el procés jt9.exe - + KillByName return code: %1 Codi de retorn de KillByName: %1 - + Error removing "%1" Error en eliminar "%1" - + Click OK to retry Fes clic a D'acord per tornar-ho a provar - - + + Improper mode Mode inadequat - - + + File Open Error Error al obrir l'arxiu - - - - - + + + + + Cannot open "%1" for append: %2 No es pot obrir "%1" per annexar: %2 - + Error saving c2 file Error en desar l'arxiu c2 - + Error in Sound Input Error a la entrada de so - + Error in Sound Output Error en la sortida de so - - - + + + Single-Period Decodes Descodificacions d'un sol període - - - + + + Average Decodes Mitjans descodificats - + Change Operator Canvi d'Operador - + New operator: Operador Nou: - + Status File Error Error d'estat de l'arxiu - - + + Cannot open "%1" for writing: %2 No es pot obrir "%1" per escriure: %2 - + Subprocess Error Error de subprocés - + Subprocess failed with exit code %1 Ha fallat el subprocés amb el codi de sortida %1 - + Running: %1 %2 Corrent: %1 %2 - + Subprocess error Error de subprocés - + Reference spectrum saved Guarda l'espectre de referència - + Invalid data in fmt.all at line %1 Les dades no són vàlides a fmt.all a la línia %1 - + Good Calibration Solution Solució de bona calibració - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -4040,17 +4066,17 @@ La llista es pot mantenir a la configuració (F2). %9%L10 Hz</pre> - + Delete Calibration Measurements Suprimeix les mesures de calibració - + The "fmt.all" file will be renamed as "fmt.bak" L'arxiu "fmt.all" serà renombrat com a "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -4058,27 +4084,27 @@ La llista es pot mantenir a la configuració (F2). "Els algoritmes, codi font, aspecte de WSJT-X i programes relacionats i les especificacions de protocol per als modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 són Copyright (C) 2001-2020 per un o més dels següents autors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q i altres membres del grup de desenvolupament de WSJT. " - + No data read from disk. Wrong file format? No es llegeixen dades del disc. Format de l'arxiu incorrecte ? - + Confirm Delete Confirma Esborrar - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? Estàs segur que vols esborrar tots els arxius *.wav i *.c2"%1" ? - + Keyboard Shortcuts Dreceres de teclat - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4265,12 +4291,12 @@ La llista es pot mantenir a la configuració (F2). </table> - + Special Mouse Commands Ordres especials del ratolí - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4336,42 +4362,42 @@ La llista es pot mantenir a la configuració (F2). </table> - + No more files to open. No s’obriran més arxius. - + Spotting to PSK Reporter unavailable No hi ha espots a PSK Reporter - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. Tria una altra freqüència de TX. El WSJT-X no transmetrà de manera conscient un altre mode a la sub-banda WSPR a 30 m. - + WSPR Guard Band Banda de Guàrdia WSPR - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. Tria una altra freqüència de treball. WSJT-X no funcionarà en mode Fox a les sub-bandes FT8 estàndard. - + Fox Mode warning Avís de mode Fox - + Last Tx: %1 Últim TX: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4382,120 +4408,120 @@ Per fer-ho, comprova "Activitat operativa especial" i Concurs EU VHF a la Configuració | Pestanya avançada. - + Should you switch to ARRL Field Day mode? Has de canviar al mode de Field Day de l'ARRL ? - + Should you switch to RTTY contest mode? Has de canviar al mode de concurs RTTY? - - - - + + + + Add to CALL3.TXT Afegeix a CALL3.TXT - + Please enter a valid grid locator Introduïu un locator vàlid - + Cannot open "%1" for read/write: %2 No es pot obrir "%1" per llegir o escriure: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? %1 ja és a CALL3.TXT, vols substituir-lo ? - + Warning: DX Call field is empty. Avís: el camp de indicatiu DX està buit. - + Log file error Error a l'arxiu de log - + Cannot open "%1" No es pot obrir "%1" - + Error sending log to N1MM Error al enviar el log a N1MM - + Write returned "%1" Escriptura retornada "%1" - + Stations calling DXpedition %1 Estacions que criden a DXpedition %1 - + Hound Hound - + Tx Messages Missatges de TX - - - + + + Confirm Erase Confirma Esborrar - + Are you sure you want to erase file ALL.TXT? Estàs segur que vols esborrar l'arxiu ALL.TXT ? - - + + Confirm Reset Confirma que vols Restablir - + Are you sure you want to erase your contest log? Estàs segur que vols esborrar el log del concurs ? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. Si fas això, suprimiràs tots els registres de QSO del concurs actual. Es conservaran a l'arxiu de log ADIF, però no es podran exportar al log de Cabrillo. - + Cabrillo Log saved Log Cabrillo desat - + Are you sure you want to erase file wsjtx_log.adi? Estàs segur que vols esborrar l'arxiu wsjtx_log.adi ? - + Are you sure you want to erase the WSPR hashtable? Estàs segur que vols esborrar la taula del WSPR ? @@ -4504,60 +4530,60 @@ ja és a CALL3.TXT, vols substituir-lo ? Les característiques de VHF tenen un avís - + Tune digital gain Guany de sintonització digital - + Transmit digital gain Guany digital de transmissió - + Prefixes Prefixos - + Network Error Error de xarxa - + Error: %1 UDP server %2:%3 Error: %1 UDP server %2:%3 - + File Error Error a l'arxiu - + Phase Training Disabled Entrenament de fase Desactivat - + Phase Training Enabled Entrenament de fase activat - + WD:%1m WD:%1m - - + + Log File Error Error a l'arxiu de log - + Are you sure you want to clear the QSO queues? Estàs segur que vols esborrar les cues de QSO ? @@ -4904,22 +4930,21 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. S'ha produït un error obrint el dispositiu d'entrada d'àudio. - + An error occurred during read from the audio input device. S'ha produït un error de lectura des del dispositiu d'entrada d'àudio. - Audio data not being fed to the audio input device fast enough. - Les dades d'àudio no s'envien al dispositiu d'entrada d'àudio prou ràpid. + Les dades d'àudio no s'envien al dispositiu d'entrada d'àudio prou ràpid. - + Non-recoverable error, audio input device not usable at this time. Error no recuperable, el dispositiu d'entrada d'àudio no es pot utilitzar ara. @@ -4934,37 +4959,37 @@ Error(%2): %3 El format d'àudio d'entrada sol·licitat no és compatible amb el dispositiu. - + Failed to initialize audio sink device Error a l'inicialitzar el dispositiu de descarrega d'àudio - + Idle Inactiu - + Receiving Rebent - + Suspended Suspès - + Interrupted Interromput - + Error Error - + Stopped Aturat @@ -4972,67 +4997,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. S'ha produït un error obrint el dispositiu de sortida d'àudio. - + An error occurred during write to the audio output device. S'ha produït un error escribint en el dispositiu de sortida d'àudio. - + Audio data not being fed to the audio output device fast enough. Les dades d'àudio no s'envien al dispositiu de sortida d'àudio prou ràpid. - + Non-recoverable error, audio output device not usable at this time. Error no recuperable, dispositiu de sortida d'àudio no utilitzable ara. - + Requested output audio format is not valid. El format sol·licitat d'àudio de sortida no és vàlid. - + Requested output audio format is not supported on device. El format sol·licitat d'àudio de sortida no és compatible amb el dispositiu. - + No audio output device configured. No hi ha configurat cap dispositiu de sortida d'àudio. - + Idle Inactiu - + Sending Enviant - + Suspended Suspès - + Interrupted Interromput - + Error Error - + Stopped Aturat @@ -5040,22 +5065,22 @@ Error(%2): %3 StationDialog - + Add Station Afegir estació - + &Band: &Banda: - + &Offset (MHz): &Desplaçament en MHz: - + &Antenna: &Antena: @@ -6053,7 +6078,7 @@ interfície de ràdio funcioni correctament. Targeta de so - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -6066,46 +6091,46 @@ desactivats, en cas contrari emetreu els sons del sistema generats durant els períodes de transmissió. - + Select the audio CODEC to use for receiving. Selecciona el CODEC d'àudio que cal utilitzar per rebre. - + &Input: &Entrada: - + Select the channel to use for receiving. Selecciona el canal a utilitzar per a rebre. - - + + Mono Mono - - + + Left Esquerra - - + + Right Dreta - - + + Both Tots dos - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -6121,7 +6146,7 @@ els dos canals. Activa les funcions de VHF i submode - + Ou&tput: Sor&tida: @@ -6376,67 +6401,67 @@ per avaluar la propagació i el rendiment del sistema. <html><head/><body><p>Introdueix el número de port del servei del servidor UDP al qual WSJT-X hauria d'enviar les actualitzacions. Si és zero, no s’emetran actualitzacions.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p>Amb aquesta habilitat, WSJT-X acceptarà de nou algunes sol·licituds d’un servidor UDP que rep missatges de descodificació.</p></body></html> - + Accept UDP requests Accepta sol·licituds UDP - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p>Indica l'acceptació d'una sol·licitud UDP entrant. L’efecte d’aquesta opció varia en funció del sistema operatiu i del gestor de finestres, la seva intenció és notificar l’acceptació d’una sol·licitud UDP entrant encara que aquesta aplicació estigui minimitzada o oculta.</p></body></html> - + Notify on accepted UDP request Notifica-la sobre la sol·licitud acceptada d’UDP - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p>Restaura la finestra al mínim si s’accepta una sol·licitud UDP.</p></body></html> - + Accepted UDP request restores window La finestra de restauració de la sol·licitud UDP es acceptada - + Secondary UDP Server (deprecated) Servidor UDP secundari (obsolet) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p>Quan es marca, WSJT-X transmetrà un contacte registrat en format ADIF al nom d'amfitrió i port configurats. </p></body></html> - + Enable logged contact ADIF broadcast Habilita la transmissió ADIF de contacte registrad - + Server name or IP address: Nom del servidor o adreça IP: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>Nom d'amfitrió opcional del programa N1MM Logger+ per rebre transmissions ADIF UDP. Generalment és "localhost" o adreça IP 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Nom d'amfitrió</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">adreça IPv4</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">adreça IPv6</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adreça de grup multicast IPv4</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Adreça de grup multicast IPv6</li></ul><p>Si esborres aquest camp, es desactivarà la transmissió d’informació ADIF a través d’UDP.</p></body></html> - + Server port number: Número de port del servidor: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>Introdueix el número de port que hauria d’utilitzar WSJT-X per a les emissions d'UDP d’informació de registre ADIF. Per N1MM Logger+, aquest valor hauria de ser 2333. Si aquest és zero, no es transmetran actualitzacions.</p></body></html> @@ -6928,63 +6953,63 @@ Fes clic amb el botó dret per a les opcions d'inserció i eliminació.Versió d’aplicació - + Another instance may be running Una altra instància pot ser que s'estigui executant - + try to remove stale lock file? intenteu eliminar l'arxiu de bloqueig no realitzat? - + Failed to create a temporary directory No s'ha pogut crear el directori temporal - - + + Path: "%1" Ruta: "%1" - + Failed to create a usable temporary directory No s'ha pogut crear un directori temporal utilitzable - + Another application may be locking the directory Una altra aplicació pot ser que bloquegi del directori - + Failed to create data directory No s'ha pogut crear el directori de dades - + path: "%1" Ruta: "%1" - + Shared memory error Error de memòria compartida - + Unable to create shared memory segment No es pot crear el segment de memòria compartida - + Sub-process error Error de subprocés - + Failed to close orphaned jt9 process No s'ha pogut tancar el procés jt9 orfe diff --git a/translations/wsjtx_da.ts b/translations/wsjtx_da.ts index e06c93fd4..3acc2f102 100644 --- a/translations/wsjtx_da.ts +++ b/translations/wsjtx_da.ts @@ -369,75 +369,75 @@ Configuration::impl - - - + + + &Delete &Slet - - + + &Insert ... &indsæt ... - + Failed to create save directory Fejl ved oprettelse af mappe til at gemme i - + path: "%1% sti: "%1% - + Failed to create samples directory Fejl i oprettelsen af mappe til eksempler - + path: "%1" sti: "%1" - + &Load ... &Hent ... - + &Save as ... &Gem som ... - + &Merge ... &Indflette ... - + &Reset &Reset - + Serial Port: Seriel Port: - + Serial port used for CAT control Seriel port til CAT kontrol - + Network Server: Netværk Server: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -452,12 +452,12 @@ Formater: [IPv6-address]:port - + USB Device: USB Enhed: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -468,8 +468,8 @@ Format: [VID[:PID[:VENDOR[:PRODUCT]]]] - - + + Invalid audio input device Foekert audio input enhed @@ -478,150 +478,156 @@ Format: Forkert audio output enhed - + Invalid audio output device Forkert Audio output Enhed - + Invalid PTT method Forkert PTT metode - + Invalid PTT port Forkert PTT port - - + + Invalid Contest Exchange Forkert Contest Udveksling - + You must input a valid ARRL Field Day exchange Indsæt et valid ARRL Field Day exchange - + You must input a valid ARRL RTTY Roundup exchange Indsæt et valid ARRL RTTY Roundup exchange - + Reset Decode Highlighting Nulstil dekode markering - + Reset all decode highlighting and priorities to default values Indstil alle dekode markeringer og prioriteringer til default - + WSJT-X Decoded Text Font Chooser WSJT-X Dekodet tekst Font vælger - + Load Working Frequencies Hent Frekvens liste - - - + + + Frequency files (*.qrg);;All files (*.*) Frekvens fil *.qrg);;All files (*.*) - + Replace Working Frequencies Erstat frekvensliste - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? Er du sikker på du vil kassere dine nuværende frekvensliste og erstatte den med denne frekvensliste? - + Merge Working Frequencies Indflet Frevens liste - - - + + + Not a valid frequencies file Ikke en gyldig Frekvens liste fil - + Incorrect file magic Forkert fil Magic - + Version is too new Version for ny - + Contents corrupt Inhold ugyldigt - + Save Working Frequencies Gem frekvens liste - + Only Save Selected Working Frequencies Gemmer kun de valgte frekvenser til listen - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. Er du sikker på du kun vil gemme de valgte frekvenser i Frekvenslisten. Klik nej for gemme alle. - + Reset Working Frequencies Reset frekvens liste - + Are you sure you want to discard your current working frequencies and replace them with default ones? Er du sikker på du vil kassere dine nuværende frekvensliste og erstatte dem med standard frekvenser? - + Save Directory Gemme Mappe - + AzEl Directory AzEL Mappe - + Rig control error Radio kontrol fejl - + Failed to open connection to rig Fejl i etablering af forbindelse til radio - + Rig failure Radio fejl + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1444,22 +1450,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency Tilføj Frekvens - + IARU &Region: IARU &Region: - + &Mode: &Mode: - + &Frequency (MHz): &Frekvens (Mhz): @@ -1581,180 +1587,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Hamlib initialiseringsfejl - + Hamlib settings file error: %1 at character offset %2 Hamlib fejl i ved indstillings fil : %1 ved karakter offset %2 - + Hamlib settings file error: top level must be a JSON object Hamlib indstillings fil fejl: Top niveau skal være et JSON objekt - + Hamlib settings file error: config must be a JSON object Hamlib indstillings fil fejl: konfiguration skal være et JSON objekt - + Unsupported CAT type Ikke under støttet CAT type - + Hamlib error: %1 while %2 Hamlib fejl: %1 med %2 - + opening connection to rig Åbner forbindelse til radio - + getting current frequency Henter nuværende frekvens - + getting current mode Henter nuværende mode - - + + exchanging VFOs Skifter VFOer - - + + getting other VFO frequency Henter anden VFO - + getting other VFO mode Henter anden VFO Mode - - + + setting current VFO Inderstiller nuværende VFO - + getting frequency Henter frekvens - + getting mode Henter mode - - - + + + getting current VFO Henter nuværende VFO - - - - + + + + getting current VFO frequency Henter nuværende VFO frekvens - - - - - - + + + + + + setting frequency Indstiller frekvens - - - - + + + + getting current VFO mode Henter nuværende VFO mode - - - - - + + + + + setting current VFO mode Indstiller nuværende VFO mode - - + + setting/unsetting split mode Indstiller/Fjerner spilt mode - - + + setting split mode Indstiller split mode - + setting split TX frequency and mode Indstiller split TX frekvens og mode - + setting split TX frequency Indstiller split frekvens - + getting split TX VFO mode Henter split TX VFO mode - + setting split TX VFO mode Indstiller split TX VFO mode - + getting PTT state Henter PTT status - + setting PTT on Sætter PTT on - + setting PTT off Sætter PTT off - + setting a configuration item Indstilling af konfigurations element - + getting a configuration item Henter konfigirations element @@ -2085,196 +2091,196 @@ Fejl(%2): %3 WSJT-X by K1JT - - - - - - - - + + + + + + + + Band Activity Bånd Aktivitet - - + + UTC dB DT Freq Dr UTC dB DT Frekv Dr - - - - - - - + + + + + + + Rx Frequency Rx frekvens - + CQ only Kun CQ - + Enter this QSO in log Indsæt denne QSO i Log - + Log &QSO Log &QSO - + Stop monitoring Stop monitorering - + &Stop &Stop - + Toggle monitoring On/Off Skift monitorering On/Off - + &Monitor &Monitor - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>Slet hjre vindue. Dobbelt-klik for at slette begge vinduer.</p></body></html> - + Erase right window. Double-click to erase both windows. Slet højre vindue. Dobbelt klik for at slette begge vinduer. - + &Erase &Slet - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body> <p> Slet det samlede meddelelsesgennemsnit. </p> </body> </html> - + Clear the accumulating message average. Slet det samlede meddelses gennemsnit. - + Clear Avg Slet AVG - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body> <p> Dekod den seneste Rx-periode på QSO-frekvens </p> </body> </html> - + Decode most recent Rx period at QSO Frequency Dekod den seneste Rx-periode på QSO-frekvens - + &Decode &Dekod - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body><p>Skift af Auto-Tx On/Off</p></body></html> - + Toggle Auto-Tx On/Off Skift Auto Tx On/Off - + E&nable Tx A&ktiver Tx - + Stop transmitting immediately Stop TX med det samme - + &Halt Tx &Stop Tx - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>Skift mellem On/Off af TX Tone</p></body></html> - + Toggle a pure Tx tone On/Off Skift mellem On/Off af TX Tone - + &Tune &Tune - + Menus Menu - + Percentage of minute sequences devoted to transmitting. Procentdel af minut sekvens dedikeret til sending. - + Prefer Type 1 messages Foretræk Type 1 meddelse - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>Send i næste sekvens.</p></body></html> - + USB dial frequency USB dial frekvens - + 14.078 000 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body> <p> 30dB anbefales, når der kun er støj til stede <br/> Grønt er godt <br/> Rødt ved klipning kan forekomme <br/> Gul, når den er for lav </p> </ body > </ html> - + Rx Signal Rx Signal - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2285,343 +2291,343 @@ Rød ved klipping kan forekomme Gul er for lavt - + DX Call DX kaldesignal - + DX Grid DX Grid - + Callsign of station to be worked Kaldesignal på den der køres - + Search for callsign in database Kig efter kaldesignalet i databasen - + &Lookup &Slå op - + Locator of station to be worked Lokator på den der køres - + Az: 251 16553 km Az: 251 16553 km - + Add callsign and locator to database Tilføj kaldesignal og locator til Log databasen - + Add Tilføj - + Pwr Pwr - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body> <p> Er den orange eller rød er der sket en Radiokontrol fejl og så skal du klikke for at nulstille og læse frekvensen. S betyder split mode. </p> </body> </html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. Hvis den er orange eller rød har der været en Radiokontrol fejl. Så skal der klikkes for nulstille og læse frekvensen. S betyder split mode. - + ? ? - + Adjust Tx audio level Juster Tx audio niveau - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body> <p> Vælg bånd eller indtast frekvens i MHz eller indtast kHz forøgelse efterfulgt af k. </p> </body> </html> - + Frequency entry Indsæt Frekvens - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. Vælg bånd du vil operere på eller indtast frekvens i Mhz eller indtast Khz efterfulgt af k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body> <p> Marker for at holde Tx-frekvensen, når du dobbeltklikker på dekodet tekst. </p> </body> </html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. Marker for at låse Tx frekvens når der dobbeltklikkes på en dekodet tekst. - + Hold Tx Freq Hold Tx Frekv - + Audio Rx frequency Audio Rx frekvens - - - - - + + + + + Hz Hz - - + + Rx Rx - - + + Set Tx frequency to Rx Frequency Sæt Tx frekvens til Rx frekvens - + - + Frequency tolerance (Hz) Frekvens tolerance (Hz) - - + + F Tol F Tol - - + + Set Rx frequency to Tx Frequency Sæt Rx frekevens til Tx Frekvens - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body> <p> Synkroniseringsgrænse. Lavere tal accepterer svagere synkroniseringssignaler. </p> </body> </html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. Synkroniseringsgrænse. Lavere tal accepterer svagere synkroniseringssignaler. - + Sync Synk - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>Marker for at bruge kort msg format.</p></body></html> - + Check to use short-format messages. Marker for at bruge kort msg format. - + Sh Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>Marker for at aktivere JT9 Fast Mode</p></body></html> - + Check to enable JT9 fast modes Marker for aktivering af JT9 Fast Mode - - + + Fast Fast - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body> <p> Marker for at aktivere automatisk sekventering af Tx-meddelelser baseret på modtagne meddelelser. </p> </body> </html> - + Check to enable automatic sequencing of Tx messages based on received messages. Marker for at aktivere automatisk sekventering af Tx-meddelelser baseret på modtagne meddelelser. - + Auto Seq Auto Sekv - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body> <p> Marker for at kalde den første dekodede som svarer på min CQ. </p> </body> </html> - + Check to call the first decoded responder to my CQ. Marker for at kalde den første som svarer på min CQ. - + Call 1st Kald 1st - + Check to generate "@1250 (SEND MSGS)" in Tx6. Marker for at generere "@1250 (SEND MSGS)" in Tx6. - + Tx6 Tx6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body> <p> Marker for Tx på lige sekunder i minuttet eller sekvenser, der starter ved 0; fjern markeringen for ulige sekvenser. </p> </body> </html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. Marker til Tx på lige sekunder i minuttet eller sekvenser, der starter ved 0; fjern markeringen for ulige sekvenser. - + Tx even/1st Tx Lige/1st - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body><p>Frekvens hvor der kaldes CQ på i kHz over de nuværende Mhz</p></body></html> - + Frequency to call CQ on in kHz above the current MHz Frekvens hvor der kaldes CQ i Khz over de nuværende Mhz - + Tx CQ Tx CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body> <p> Marker for at kalde CQ på &quot; Tx CQ &quot; frekvens. Rx vil være på den aktuelle frekvens, og CQ-meddelelsen vil indeholde den aktuelle Rx-frekvens, så modparten ved, hvilken frekvens der skal svares på. </p> <p> Ikke tilgængelig for ikke-standard kaldesignaler. </p> </body> </ html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. Marker for at kalde CQ på "TX CQ" frekvens. Rx vil være på den aktuelle frekvens, og CQ-meddelelsen vil indeholde den aktuelle Rx-frekvens, så modparten ved, hvilken frekvens der skal svares på. Ikke tilgængelig for ikke-standard kaldesignaler. - + Rx All Freqs Rx Alle Frekv - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body> <p> Submode bestemmer toneafstanden; A er det smalleste. </p> </body> </html> - + Submode determines tone spacing; A is narrowest. Submode bestemmer toneafstanden; A er det smalleste. - + Submode Submode - - + + Fox Fox - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>Marker for at monitere Sh meddelser.</p></body></html> - + Check to monitor Sh messages. Marker for monitering af Sh meddelser. - + SWL SWL - + Best S+P Best S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body> <p> Marker dennee for at starte opsamling af kalibreringsdata. <br/> Mens måling af kalibreringskorrektion er visning deaktiveret. <br/> Når denne ikke er markeret, kan du se kalibreringsresultaterne. </p> </ body> </ html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2630,206 +2636,216 @@ Mens foregår måling af kalibreringskorrektion er visning deaktiveret. Når den ikke er markeret, kan du se kalibreringsresultaterne. - + Measure Mål kalibrering - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body> <p> Signalrapport: Signal-til-støj-forhold i 2500 Hz referencebåndbredde (dB). </p> </body> </html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). Signalrapport: Signal-til-støj-forhold i 2500 Hz referencebåndbredde (dB). - + Report Rapport - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>Tx/Rx eller Frekvens kalibrerings sekvenslængde</p></body></html> - + Tx/Rx or Frequency calibration sequence length Tx/Rx eller Frekvens kalibrerings sekvenslængde</p></body></html> - - + + s s - - + + T/R T/R - + Toggle Tx mode Skift TX mode - + Tx JT9 @ Tx JT9@ - + Audio Tx frequency Audio Tx frekvens - - + + Tx TX - + Tx# TX# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body> <p> Dobbeltklik på et CQ opkald for at den pågældende kommer i kø til næste QSO. </p> </body> </html> - + + F High + + + + + F Low + + + + Double-click on another caller to queue that call for your next QSO. Dobbeltklik på et andet CQ opkald for at den pågældende kommer i kø til næste QSO. - + Next Call Næste Kaldesignal - + 1 1 - - - + + + Send this message in next Tx interval Send denne meddelse i næste Tx periode - + Ctrl+2 Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body> <p> Send denne meddelelse i næste Tx-interval </p> <p> Dobbeltklik for at skifte brug af Tx1-meddelelsen til at starte en QSO med en station (ikke tilladt for type 1 sammensatte opkald) </p> </body> </html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Send denne meddelelse i næste Tx-periode. Dobbeltklik for at skifte brug af Tx1-meddelelsen til at starte en QSO med en station (ikke tilladt for type 1 indehavere af sammensatte opkald) - + Ctrl+1 CTRL+1 - - - - + + + + Switch to this Tx message NOW Skift til denne Tx meddelse nu - + Tx &2 TX &2 - + Alt+2 Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> html><head/><body> <p> Skift til denne Tx-meddelelse NU </p> <p> Dobbeltklik for at skifte brug af Tx1-meddelelsen til at starte en QSO med en station (ikke tilladt for type 1 sammensatte kaldesignaler) </p> </body> </html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Skift til denne Tx meddelse NU Dobbelt klik for at skifte brug af Tx1 meddelse for at starte QSO med en station (ikke tilladt for type 1 sammensatte kaldesignaler) - + Tx &1 Tx &1 - + Alt+1 Alt+1 - + Ctrl+6 CTRL+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Send denne meddelse i næste Tx periode</p><p>Dobbelt klik for at resette til standard 73 message</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message Send denne meddelse i næste Tx periode Dobbelt klik for at resette til standard 73 message - + Ctrl+5 Ctrl+5 - + Ctrl+3 CTRL+3 - + Tx &3 Tx &3 - + Alt+3 Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p> Send denne meddelelse i næste Tx periode </p> <p> Dobbeltklik for at skifte mellem RRR og RR73-meddelelser i Tx4 (ikke tilladt for type 2 sammensatte kaldesignaler)</p><p> RR73 meddelelser skal kun bruges, når du med rimelig sikkerhed er overbevist om, at der ikke kræves gentagne meddelelser</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2838,17 +2854,17 @@ Dobbeltklik for at skifte mellem RRR og RR73-meddelelser i Tx4 (ikke tilladt for RR73-meddelelser skal kun bruges, når du med rimelig sikkerhed er overbevist om, at der ikke kræves gentagne meddelelser - + Ctrl+4 Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p> Skift til denne Tx-meddelelse NU</p><p>Dobbeltklik for at skifte mellem RRR og RR73-meddelelser i Tx4 (ikke tilladt for type2 sammensatte kaldesignaler)</p><p>RR73-meddelelser skal kun bruges, når du med rimelighed er overbevist om, at der ikke kræves gentagne meddelelser </p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2857,64 +2873,64 @@ Dobbeltklik for at skifte mellem RRR og RR73-meddelelser i Tx4 (ikke tilladt for RR73-meddelelser skal kun bruges, når du med rimelig sikkerhed er overbevist om, at der ikke kræves gentagne meddelelser - + Tx &4 TX &4 - + Alt+4 Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Skift til denne Tx meddelse NU</p><p>Dobbelt klik for at vende tilbage til standard 73 message</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message Skift til denne Tx meddelse NU Dobbelt klik for at vende tilbage til standard 73 meddelse - + Tx &5 Tx&5 - + Alt+5 Alt+5 - + Now Nu - + Generate standard messages for minimal QSO Generer standard meddelse til minimal QSO - + Generate Std Msgs Generate Std Medd - + Tx &6 Tx&6 - + Alt+6 Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2925,26 +2941,36 @@ Tryk på på Enter for indsætte teksten til makro listen. Makro listen kan også ændfres i Inderstillinger (F2). - + Queue up the next Tx message Sat i kø til næste Tx meddelse - + Next Næste - + 2 ? 2 - + FST4W FST4W + + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + Calling CQ Kalder CQ @@ -2954,8 +2980,8 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Generer CQ meddelse - - + + CQ CQ @@ -2984,7 +3010,7 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Generer meddelse som svar på et CQ - + Grid Grid @@ -3025,138 +3051,138 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). 3 - + Max dB Maks dB - + CQ AF CQ AF - + CQ AN CQ AN - + CQ AS CQ AS - + CQ EU CQ EU - + CQ NA CQ NA - + CQ OC CQ OC - + CQ SA CQ SA - + CQ 0 CQ 0 - + CQ 1 CQ 1 - + CQ 2 CQ 2 - + CQ 3 CQ 3 - + CQ 4 CQ 4 - + CQ 5 CQ 5 - + CQ 6 CQ 6 - + CQ 7 CQ 7 - + CQ 8 CQ 8 - + CQ 9 CQ 9 - + Reset Reset - + N List N Liste - + N Slots N slots - - - - - - - + + + + + + + Random Tilfældig - + Call Kaldesignal - + S/N (dB) S/N (dB) - + Distance Distance - + More CQs Flere CQ @@ -3165,158 +3191,158 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Procen af en 2 minutters sekvens dedikeret til sending. - - + + % % - + Tx Pct Tx Pct - + Band Hopping Bånd hopping - + Choose bands and times of day for band-hopping. Vælg bånd og tid på dagen for Bånd-Hopping. - + Schedule ... Tidskema ... - + 1/2 1/2 - + 2/2 2/2 - + 1/3 1/3 - + 2/3 2/3 - + 3/3 3/3 - + 1/4 1/4 - + 2/4 2/4 - + 3/4 3/4 - + 4/4 4/4 - + 1/5 1/5 - + 2/5 2/5 - + 3/5 3/5 - + 4/5 4/5 - + 5/5 5/5 - + 1/6 1/6 - + 2/6 2/6 - + 3/6 3/6 - + 4/6 4/6 - + 5/6 5/6 - + 6/6 6/6 - + Upload decoded messages to WSPRnet.org. Uoload dekodet meddelser til WSPRnet.org. - + Upload spots Upload spots - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>6-cifrede locatorer kræver 2 forskellige meddelelser for at blive sendt, den anden indeholder den fulde locator, men kun et hashet kaldesignal. Andre stationer skal have dekodet den første gang, før de kan dekode dit kaldesignal i den anden meddelse. Marker denne indstilling for kun at sende 4-cifrede locatorer, hvis den vil undgå to meddelelsesprotokollen.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. 6 cifrede locatorer kræver 2 forskellige meddelelser for at blive sendt, den anden indeholder den fulde locator, men kun et hashet kaldesignal. Andre stationer skal have dekodet den første gang, før de kan dekode dit kaldesignal i den anden meddelse. Marker denne indstilling for kun at sende 4-cifrede locatorer, hvis du vil undgå to meddelelses protokollen. - + Quick-Start Guide to FST4 and FST4W Quick Start Guide for FST4 og FST4W - + FST4 FST4 @@ -3329,7 +3355,7 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Fortrækker type 1 meddelse - + No own call decodes Ingen dekodning af eget kaldesignal @@ -3338,62 +3364,62 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Tx i den næste 2 minutters sekvens. - + Tx Next Tx Næste - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. Indsæt Tx power i dBm (dB over 1mW) som en del af WSPR meddelse. - + NB NB - + File Fil - + View Vis/Se - + Decode Dekod - + Save Gem - + Help Hjælp - + Mode Mode - + Configurations Konfiguration - + Tools Værktøjer - + Exit Afslut @@ -3406,87 +3432,87 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). F2 - + About WSJT-X Om WSJT-X - + Waterfall Vandfald - + Open Åbne - + Ctrl+O Ctrl+o - + Open next in directory Åben den næste i mappe - + Decode remaining files in directory Dekod resterende filer i mappen - + Shift+F6 Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir Slet alle *.wav && *.c2 filer i mappen Gemt - + None Ingen - + Save all Gem alt - + Online User Guide Online Bruger Manual - + Keyboard shortcuts Tastetur genveje - + Special mouse commands Specielle muse kommandoer - + JT9 JT9 - + Save decoded Gem dekodet - + Normal Normal - + Deep Dybt @@ -3495,12 +3521,12 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Monitor OFF ved start - + Erase ALL.TXT Slet ALL.TXT - + Erase wsjtx_log.adi Slet wsjtx_log.adi @@ -3533,12 +3559,12 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Dobbelt-klik på et kaldesignal for at sætte TX ON - + F7 F7 - + Runaway Tx watchdog Runaway Tx vagthund @@ -3551,12 +3577,12 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Tx frekv låst til Rx frekv - + JT65 JT65 - + JT9+JT65 JT+JT65 @@ -3573,147 +3599,147 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Vis DXCC og Worked B4 status - + Astronomical data Astronomi data - + List of Type 1 prefixes and suffixes Liste over Type 1 prefix og suffix - + Settings... Indstillinger... - + Local User Guide Lokal User Manual - + Open log directory Åben Logfil mappe - + JT4 JT4 - + Message averaging Meddelse gennemsnit - + Enable averaging Aktiver gennemsnit - + Enable deep search Aktiver Dyb dekodning - + WSPR WSPR - + Echo Graph Ekko graf - + F8 F8 - + Echo Ekko - + EME Echo mode EME Ekko mode - + ISCAT ISCAT - + Fast Graph Fast Graph - + F9 F9 - + &Download Samples ... &Download eksempler ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>Download audio filer eksempler som demonstrerer de forskellige modes.</p></body></html> - + MSK144 MSK144 - + QRA64 QRA64 - + Release Notes Release Notes - + Enable AP for DX Call Aktiver AP for DX kaldesignal - + FreqCal FrekvCal - + Measure reference spectrum Måler reference spectrum - + Measure phase response Måler fase response - + Erase reference spectrum Slet reference spektrum - + Execute frequency calibration cycle Kør en frekvens kalibrerings sekvens - + Equalization tools ... Equalization værktøjer ... @@ -3726,48 +3752,48 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Eksperimental LF/MF mode - + FT8 FT8 - - + + Enable AP Aktiver AP - + Solve for calibration parameters Løs for kalibrerings parametre - + Copyright notice Copyright notits - + Shift+F1 Shift+F1 - + Fox log Fox Log - + FT8 DXpedition Mode User Guide FT8 DXpedition Mode bruger guide - + Reset Cabrillo log ... Reset Cabrillo log ... - + Color highlighting scheme Farve skema @@ -3776,7 +3802,7 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Contest Log - + Export Cabrillo log ... Eksporter Cabrillo log ... @@ -3785,49 +3811,49 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). Quick-Start Guide til WSJT-X 2.0 - + Contest log Contest log - + Erase WSPR hashtable Slet WSPR Hash tabel - + FT4 FT4 - + Rig Control Error Radio kontrol fejl - - - + + + Receiving Modtager - + Do you want to reconfigure the radio interface? Vil du rekonfigurere radio interface? - + %1 (%2 sec) audio frames dropped %1 (%2 sec) audio frames droppet - + Audio Source Audio kilde - + Reduce system load Reducer system belasning @@ -3836,194 +3862,194 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). For stort tab - %1 (%2 sec) audio frames mistet - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Error Scanning ADIF Log Fejl ved scanning af Adif Log - + Scanned ADIF log, %1 worked before records created Scannet ADIF log, %1 worked B4 oprettede poster - + Error Loading LotW Users Data Fejl ved indlæsning af LotW bruger Data - + Error Writing WAV File Fejl ved skrivning af WAV Fil - + Enumerating audio devices - + Configurations... Konfigurationer... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message Meddelse - + Error Killing jt9.exe Process Fejl ved lukning af jt9.exe processen - + KillByName return code: %1 KillByName return code: %1 - + Error removing "%1" Fejl ved fjernelse af "%1" - + Click OK to retry Klik OK for at prøve igen - - + + Improper mode Forkert mode - - + + File Open Error Fejl ved åbning af fil - - - - - + + + + + Cannot open "%1" for append: %2 Kan ikke åbne "%1" for at tilføje: %2 - + Error saving c2 file Fejl da c2 fil skulle gemmes - + Error in Sound Input Fejl i Audio input - + Error in Sound Output Fejl i Audio output - - - + + + Single-Period Decodes Enkel-Periode Dekodning - - - + + + Average Decodes Gennemsnitlig dekodning - + Change Operator Skift Operatør - + New operator: Ny Operatør: - + Status File Error Fejl i status Fil - - + + Cannot open "%1" for writing: %2 Kan ikke åbne "%1" for at skrive: %2 - + Subprocess Error Underprocess fejl - + Subprocess failed with exit code %1 Underprocess fejlede med fejlkode %1 - + Running: %1 %2 Kører: %1 %2 - + Subprocess error Underprocess fejl - + Reference spectrum saved Reference spectrum gemt - + Invalid data in fmt.all at line %1 Forkert data i fmt.all ved linje %1 - + Good Calibration Solution God Kalibrerings løsning - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -4036,17 +4062,17 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). %9%L10 Hz</pre> - + Delete Calibration Measurements Slet Kalibrerings måling - + The "fmt.all" file will be renamed as "fmt.bak" Filen fmt.all vil blive omdøbt til "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -4054,27 +4080,27 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). "Algoritmerne, kildekoden, udseendet og funktionen af ​​WSJT-X og relaterede programmer og protokolspecifikationer for Mode FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 er Copyright (C) 2001-2020 af en eller flere af følgende forfattere: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; og andre medlemmer af WSJT Development Group. " - + No data read from disk. Wrong file format? Ingen data indlæst. Forkert fil format? - + Confirm Delete Bekræft sletning - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? Er du sikker på du vil slette alle *.wav og *.c2 filer i "%1"? - + Keyboard Shortcuts Tastetur Genveje - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4217,12 +4243,12 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). </table> - + Special Mouse Commands Specielle muse kommandoer - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4288,42 +4314,42 @@ listen. Makro listen kan også ændfres i Inderstillinger (F2). </table> - + No more files to open. Ikke flere filer at åbne. - + Spotting to PSK Reporter unavailable Afsendelse af Spot til PSK Reporter ikke muligt - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. Venligst vælg en ande Tx frekvens. WSJT-X vil ikke sende med en anden Mode i WSPR området på 30m. - + WSPR Guard Band WSPR Guard bånd - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. Vælg venligst en anden VFO frekvens. WSJT-x vil ikke operere med Fox mode i standard FT8 områder - + Fox Mode warning Fox Mode advarsel - + Last Tx: %1 Senest Tx: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4334,120 +4360,120 @@ For at gøre dette skal du markere 'Speciel aktivitet' og 'EU VHF-Contest' på indstillingerne | Avanceret fane. - + Should you switch to ARRL Field Day mode? Bør du skifte til ARRL Field Day mode? - + Should you switch to RTTY contest mode? Bør du skifte til RTTY Contest mode? - - - - + + + + Add to CALL3.TXT Tilføj til CALL3.TXT - + Please enter a valid grid locator Indsæt en gyldig Grid lokator - + Cannot open "%1" for read/write: %2 Kan ikke åbne "%1" for Læse/Skrive: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? %1 er allerede i CALL3.TXT. Vil du erstatte den? - + Warning: DX Call field is empty. Advarsel: DX Call feltet er tomt. - + Log file error Log fil fejl - + Cannot open "%1" Kan ikke åbne "%1" - + Error sending log to N1MM Fejl ved afsendelse af log til N1MM - + Write returned "%1" Skrivning vendte tilbage med "%1" - + Stations calling DXpedition %1 Stationer som kalder DXpedition %1 - + Hound Hound - + Tx Messages Tx meddelse - - - + + + Confirm Erase Bekræft Slet - + Are you sure you want to erase file ALL.TXT? Er du sikker på du vil slette filen ALL.TXT? - - + + Confirm Reset Bekræft Reset - + Are you sure you want to erase your contest log? Er du sikker på du vil slette din contest log? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. Gør du dette vil alle QSOer for pågældende contest blive slettet. De bliver dog gemt i en ADIF fik, men det vil ikke være muligt at eksportere dem som Cabrillo log. - + Cabrillo Log saved Cabrillo Log gemt - + Are you sure you want to erase file wsjtx_log.adi? Er du sikker på du vil slette filen wsjtx_log.adi? - + Are you sure you want to erase the WSPR hashtable? Er du sikker på du vil slette WSPR Hash tabellen? @@ -4456,60 +4482,60 @@ er allerede i CALL3.TXT. Vil du erstatte den? VHF feature advarsel - + Tune digital gain Tune digital gain - + Transmit digital gain Transmit digital gain - + Prefixes Prefixer - + Network Error Netværks Fejl - + Error: %1 UDP server %2:%3 Error: %1 UDP server %2:%3 - + File Error Fil fejl - + Phase Training Disabled Phase Training Deaktiveret - + Phase Training Enabled Phase Training Aktiveret - + WD:%1m WD:%1m - - + + Log File Error Log Fil Fejl - + Are you sure you want to clear the QSO queues? Er du sikker du vil slette QSO køen? @@ -4856,22 +4882,21 @@ Fejl(%2): %3 SoundInput - + An error opening the audio input device has occurred. En fejl er opstået ved åbning af Audio indgangsenheden. - + An error occurred during read from the audio input device. En fejl er opstået ved læsning fra Audio enheden. - Audio data not being fed to the audio input device fast enough. - Audio bliverr ikke overført hurtigt nok til Audio enheden. + Audio bliverr ikke overført hurtigt nok til Audio enheden. - + Non-recoverable error, audio input device not usable at this time. Fejl, der ikke kan gendannes, lydindgangs enhed kan ikke bruges på dette tidspunkt. @@ -4886,37 +4911,37 @@ Fejl(%2): %3 Det ønskede Audio indgangs format understøttes ikke af enheden. - + Failed to initialize audio sink device Kunne ikke initialisere lydenheden - + Idle Venter - + Receiving Modtager - + Suspended Suspenderet - + Interrupted Afbrudt - + Error Fejl - + Stopped Stoppet @@ -4924,67 +4949,67 @@ Fejl(%2): %3 SoundOutput - + An error opening the audio output device has occurred. Fejl ved åbning af Audio udgangs enheden. - + An error occurred during write to the audio output device. Fejl ved skrivning til Audio udgangs enheden. - + Audio data not being fed to the audio output device fast enough. Audio data bliver ikke sendt hurtigt nok Audio udgangs enheden. - + Non-recoverable error, audio output device not usable at this time. Fejl, der ikke kan gendannes, lydudgangs enhed kan ikke bruges på dette tidspunkt. - + Requested output audio format is not valid. Det ønskede udgangs Audio format er ikke gyldig. - + Requested output audio format is not supported on device. Det ønskede Audio udgangs format understøttes ikke af enheden. - + No audio output device configured. Ingen audio output enhed er konfigureret. - + Idle Venter - + Sending Sender - + Suspended Suspenderet - + Interrupted Afbrudt - + Error Fejl - + Stopped Stoppet @@ -4992,22 +5017,22 @@ Fejl(%2): %3 StationDialog - + Add Station Tilføj Station - + &Band: &Bånd: - + &Offset (MHz): &Offset (Mhz): - + &Antenna: &Antenne: @@ -5995,7 +6020,7 @@ radio interface opfører sig som forventet. Lydkort - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -6013,46 +6038,46 @@ transmissionsperioder. Dage siden sidste upload - + Select the audio CODEC to use for receiving. Vælg Audio CODEC for modtagelse. - + &Input: &Input: - + Select the channel to use for receiving. Vælg kanal til modtagelse. - - + + Mono Mono - - + + Left Venstre - - + + Right Højre - - + + Both Begge - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -6068,7 +6093,7 @@ eller begge. Aktiver VHF and submode funktioner - + Ou&tput: Ou&tput: @@ -6323,67 +6348,67 @@ til vurdering af udbrednings forhold og systemydelse. <html><head/><body><p> Indtast serviceportnummeret på den UDP-server, som WSJT-X skal sende opdateringer til. Hvis dette er nul, udsendes ingen opdateringer.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p> Med denne aktiveret vil WSJT-X acceptere visse anmodninger tilbage fra en UDP-server, som modtager dekodede meddelelser.</p></body></html> - + Accept UDP requests Accepter UDP anmodninger - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p> Angiv accept af en indgående UDP-anmodning. Effekten af ​​denne indstilling varierer afhængigt af operativsystemet og window manager, dens formål er at underrette accept af en indgående UDP-anmodning, selvom denne applikation er minimeret eller skjult.</p></body></html> - + Notify on accepted UDP request Meddelse om accepteret UDP anmodning - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p> Gendan vinduet fra minimeret, hvis en UDP-anmodning accepteres.</p></body></html> - + Accepted UDP request restores window Gendan vindue fra minimeret, hvis en UDP anmodning accepteres - + Secondary UDP Server (deprecated) Sekundær UDP-server (udskrevet) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p> Når denne er markeret, vil WSJT-X sende en logget kontakt i ADIF-format til det konfigurerede værtsnavn og port.</P></body></html> - + Enable logged contact ADIF broadcast Aktiver Logged kontankt ADIF afsendelse - + Server name or IP address: Server navn eller IP adresse: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>Alternativ host navn i N1MM Logger+ program der skal modtage ADIF UDP broadcasts. Det e rnormalt 'localhost' eller ip adresse 127.0.0.1</p><p>Format:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostnavn</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 adresse</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast gruppe adresse</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Slettes dette felt vil der ikke blive udsendt broadcasting af ADIF information via UDP.</p></body></html> - + Server port number: Server port nummer: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>Indsæt portnummer som WSJT-X skal bruge til UDP broadcasts af ADIF log information. For N1MM Logger+, skal det være 2333. Hvis det er NUL vil der ikke blive udsendt broadcast.</p></body></html> @@ -6835,63 +6860,63 @@ Højre klik for at indsætte eller slette elementer. Uventet fatal fejl - + Another instance may be running En anden udgave af programmet kører måske - + try to remove stale lock file? forsøg at fjerne uaktuelle låste filer? - + Failed to create a temporary directory Fejl ved forsøg på at oprette midlertidig mappe - - + + Path: "%1" Sti: "%1" - + Failed to create a usable temporary directory Fejl i forsøg på at oprette brugbar midlertidig mappe - + Another application may be locking the directory En anden applikation spærrer måske mappen - + Failed to create data directory Kan ikke oprette Data mappe - + path: "%1" Sti: "%1" - + Shared memory error Delt hukommelse fejl - + Unable to create shared memory segment Kan ikke oprette delt hukommelse segment - + Sub-process error Under-rutine fejl - + Failed to close orphaned jt9 process Fejl ved lukning af jt9 proces diff --git a/translations/wsjtx_en.ts b/translations/wsjtx_en.ts index 60dc2593e..ed8512833 100644 --- a/translations/wsjtx_en.ts +++ b/translations/wsjtx_en.ts @@ -369,75 +369,75 @@ Configuration::impl - - - + + + &Delete - - + + &Insert ... - + Failed to create save directory - + path: "%1% - + Failed to create samples directory - + path: "%1" - + &Load ... - + &Save as ... - + &Merge ... - + &Reset - + Serial Port: - + Serial port used for CAT control - + Network Server: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -447,12 +447,12 @@ Formats: - + USB Device: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -460,156 +460,162 @@ Format: - - + + Invalid audio input device - + Invalid audio output device - + Invalid PTT method - + Invalid PTT port - - + + Invalid Contest Exchange - + You must input a valid ARRL Field Day exchange - + You must input a valid ARRL RTTY Roundup exchange - + Reset Decode Highlighting - + Reset all decode highlighting and priorities to default values - + WSJT-X Decoded Text Font Chooser - + Load Working Frequencies - - - + + + Frequency files (*.qrg);;All files (*.*) - + Replace Working Frequencies - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? - + Merge Working Frequencies - - - + + + Not a valid frequencies file - + Incorrect file magic - + Version is too new - + Contents corrupt - + Save Working Frequencies - + Only Save Selected Working Frequencies - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. - + Reset Working Frequencies - + Are you sure you want to discard your current working frequencies and replace them with default ones? - + Save Directory - + AzEl Directory - + Rig control error - + Failed to open connection to rig - + Rig failure + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1420,22 +1426,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency - + IARU &Region: - + &Mode: - + &Frequency (MHz): @@ -1554,180 +1560,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error - + Hamlib settings file error: %1 at character offset %2 - + Hamlib settings file error: top level must be a JSON object - + Hamlib settings file error: config must be a JSON object - + Unsupported CAT type - + Hamlib error: %1 while %2 - + opening connection to rig - + getting current frequency - + getting current mode - - + + exchanging VFOs - - + + getting other VFO frequency - + getting other VFO mode - - + + setting current VFO - + getting frequency - + getting mode - - - + + + getting current VFO - - - - + + + + getting current VFO frequency - - - - - - + + + + + + setting frequency - - - - + + + + getting current VFO mode - - - - - + + + + + setting current VFO mode - - + + setting/unsetting split mode - - + + setting split mode - + setting split TX frequency and mode - + setting split TX frequency - + getting split TX VFO mode - + setting split TX VFO mode - + getting PTT state - + setting PTT on - + setting PTT off - + setting a configuration item - + getting a configuration item @@ -2027,296 +2033,316 @@ Error(%2): %3 - - - - - - - - + + + + + + + + Band Activity - - + + UTC dB DT Freq Dr - - - - - - - + + + + + + + Rx Frequency - + CQ only - + Enter this QSO in log - + Log &QSO - + Stop monitoring - + &Stop - + Toggle monitoring On/Off - + &Monitor - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> - + Erase right window. Double-click to erase both windows. - + &Erase - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> - + Clear the accumulating message average. - + Clear Avg - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> - + Decode most recent Rx period at QSO Frequency - + &Decode - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> - + Toggle Auto-Tx On/Off - + E&nable Tx - + Stop transmitting immediately - + &Halt Tx - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> - + Toggle a pure Tx tone On/Off - + &Tune - + Menus - + + F High + + + + + F Low + + + + 1/2 - + 2/2 - + 1/3 - + 2/3 - + 3/3 - + 1/4 - + 2/4 - + 3/4 - + 4/4 - + 1/5 - + 2/5 - + 3/5 - + 4/5 - + 5/5 - + 1/6 - + 2/6 - + 3/6 - + 4/6 - + 5/6 - + 6/6 - + Percentage of minute sequences devoted to transmitting. - + Prefer Type 1 messages - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> - + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + + + USB dial frequency - + 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> - + Rx Signal - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2324,626 +2350,626 @@ Yellow when too low - + DX Call - + DX Grid - + Callsign of station to be worked - + Search for callsign in database - + &Lookup - + Locator of station to be worked - + Az: 251 16553 km - + Add callsign and locator to database - + Add - + Pwr - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. - + ? - + Adjust Tx audio level - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> - + Frequency entry - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. - + Hold Tx Freq - + Audio Rx frequency - - - - - + + + + + Hz - - + + Rx - - + + Set Tx frequency to Rx Frequency - + - + Frequency tolerance (Hz) - - + + F Tol - - + + Set Rx frequency to Tx Frequency - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. - + Sync - + <html><head/><body><p>Check to use short-format messages.</p></body></html> - + Check to use short-format messages. - + Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> - + Check to enable JT9 fast modes - - + + Fast - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. - + Auto Seq - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> - + Check to call the first decoded responder to my CQ. - + Call 1st - + Check to generate "@1250 (SEND MSGS)" in Tx6. - + Tx6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. - + Tx even/1st - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> - + Frequency to call CQ on in kHz above the current MHz - + Tx CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. - + Rx All Freqs - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> - + Submode determines tone spacing; A is narrowest. - + Submode - - + + Fox - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> - + Check to monitor Sh messages. - + SWL - + Best S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. - + Measure - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - + Report - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> - + Tx/Rx or Frequency calibration sequence length - - + + s - - + + T/R - + Toggle Tx mode - + Tx JT9 @ - + Audio Tx frequency - - + + Tx - + Tx# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> - + Double-click on another caller to queue that call for your next QSO. - + Next Call - + 1 - - - + + + Send this message in next Tx interval - + Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - + Ctrl+1 - - - - + + + + Switch to this Tx message NOW - + Tx &2 - + Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - + Tx &1 - + Alt+1 - + Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message - + Ctrl+5 - + Ctrl+3 - + Tx &3 - + Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required - + Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required - + Tx &4 - + Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message - + Tx &5 - + Alt+5 - + Now - + Generate standard messages for minimal QSO - + Generate Std Msgs - + Tx &6 - + Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2951,839 +2977,839 @@ list. The list can be maintained in Settings (F2). - + Queue up the next Tx message - + Next - + 2 - + Quick-Start Guide to FST4 and FST4W - + FST4 - + FST4W - - + + CQ - + Grid - + Max dB - + CQ AF - + CQ AN - + CQ AS - + CQ EU - + CQ NA - + CQ OC - + CQ SA - + CQ 0 - + CQ 1 - + CQ 2 - + CQ 3 - + CQ 4 - + CQ 5 - + CQ 6 - + CQ 7 - + CQ 8 - + CQ 9 - + Reset - + N List - + N Slots - - - - - - - + + + + + + + Random - + Call - + S/N (dB) - + Distance - + More CQs - - + + % - + Tx Pct - + Band Hopping - + Choose bands and times of day for band-hopping. - + Schedule ... - + Upload decoded messages to WSPRnet.org. - + Upload spots - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. - + No own call decodes - + Tx Next - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. - + NB - + File - + View - + Decode - + Save - + Help - + Mode - + Configurations - + Tools - + Exit - + About WSJT-X - + Waterfall - + Open - + Ctrl+O - + Open next in directory - + Decode remaining files in directory - + Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir - + None - + Save all - + Online User Guide - + Keyboard shortcuts - + Special mouse commands - + JT9 - + Save decoded - + Normal - + Deep - + Erase ALL.TXT - + Erase wsjtx_log.adi - + F7 - + Runaway Tx watchdog - + JT65 - + JT9+JT65 - + Astronomical data - + List of Type 1 prefixes and suffixes - + Settings... - + Local User Guide - + Open log directory - + JT4 - + Message averaging - + Enable averaging - + Enable deep search - + WSPR - + Echo Graph - + F8 - + Echo - + EME Echo mode - + ISCAT - + Fast Graph - + F9 - + &Download Samples ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> - + MSK144 - + QRA64 - + Release Notes - + Enable AP for DX Call - + FreqCal - + Measure reference spectrum - + Measure phase response - + Erase reference spectrum - + Execute frequency calibration cycle - + Equalization tools ... - + FT8 - - + + Enable AP - + Solve for calibration parameters - + Copyright notice - + Shift+F1 - + Fox log - + FT8 DXpedition Mode User Guide - + Reset Cabrillo log ... - + Color highlighting scheme - + Export Cabrillo log ... - + Contest log - + Erase WSPR hashtable - + FT4 - + Rig Control Error - - - + + + Receiving - + Do you want to reconfigure the radio interface? - + %1 (%2 sec) audio frames dropped - + Audio Source - + Reduce system load - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Error Scanning ADIF Log - + Scanned ADIF log, %1 worked before records created - + Error Loading LotW Users Data - + Error Writing WAV File - + Enumerating audio devices - + Configurations... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message - + Error Killing jt9.exe Process - + KillByName return code: %1 - + Error removing "%1" - + Click OK to retry - - + + Improper mode - - + + File Open Error - - - - - + + + + + Cannot open "%1" for append: %2 - + Error saving c2 file - + Error in Sound Input - + Error in Sound Output - - - + + + Single-Period Decodes - - - + + + Average Decodes - + Change Operator - + New operator: - + Status File Error - - + + Cannot open "%1" for writing: %2 - + Subprocess Error - + Subprocess failed with exit code %1 - + Running: %1 %2 - + Subprocess error - + Reference spectrum saved - + Invalid data in fmt.all at line %1 - + Good Calibration Solution - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -3792,44 +3818,44 @@ list. The list can be maintained in Settings (F2). - + Delete Calibration Measurements - + The "fmt.all" file will be renamed as "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - + No data read from disk. Wrong file format? - + Confirm Delete - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? - + Keyboard Shortcuts - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -3879,12 +3905,12 @@ list. The list can be maintained in Settings (F2). - + Special Mouse Commands - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -3920,42 +3946,42 @@ list. The list can be maintained in Settings (F2). - + No more files to open. - + Spotting to PSK Reporter unavailable - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. - + WSPR Guard Band - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. - + Fox Mode warning - + Last Tx: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -3963,176 +3989,176 @@ To do so, check 'Special operating activity' and - + Should you switch to ARRL Field Day mode? - + Should you switch to RTTY contest mode? - - - - + + + + Add to CALL3.TXT - + Please enter a valid grid locator - + Cannot open "%1" for read/write: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? - + Warning: DX Call field is empty. - + Log file error - + Cannot open "%1" - + Error sending log to N1MM - + Write returned "%1" - + Stations calling DXpedition %1 - + Hound - + Tx Messages - - - + + + Confirm Erase - + Are you sure you want to erase file ALL.TXT? - - + + Confirm Reset - + Are you sure you want to erase your contest log? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. - + Cabrillo Log saved - + Are you sure you want to erase file wsjtx_log.adi? - + Are you sure you want to erase the WSPR hashtable? - + Tune digital gain - + Transmit digital gain - + Prefixes - + Network Error - + Error: %1 UDP server %2:%3 - + File Error - + Phase Training Disabled - + Phase Training Enabled - + WD:%1m - - + + Log File Error - + Are you sure you want to clear the QSO queues? @@ -4465,22 +4491,17 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. - + An error occurred during read from the audio input device. - - Audio data not being fed to the audio input device fast enough. - - - - + Non-recoverable error, audio input device not usable at this time. @@ -4495,37 +4516,37 @@ Error(%2): %3 - + Failed to initialize audio sink device - + Idle - + Receiving - + Suspended - + Interrupted - + Error - + Stopped @@ -4533,67 +4554,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. - + An error occurred during write to the audio output device. - + Audio data not being fed to the audio output device fast enough. - + Non-recoverable error, audio output device not usable at this time. - + Requested output audio format is not valid. - + Requested output audio format is not supported on device. - + No audio output device configured. - + Idle - + Sending - + Suspended - + Interrupted - + Error - + Stopped @@ -4601,22 +4622,22 @@ Error(%2): %3 StationDialog - + Add Station - + &Band: - + &Offset (MHz): - + &Antenna: @@ -5566,7 +5587,7 @@ radio interface behave as expected. - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -5580,46 +5601,46 @@ transmitting periods. - + Select the audio CODEC to use for receiving. - + &Input: - + Select the channel to use for receiving. - - + + Mono - - + + Left - - + + Right - - + + Both - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -5642,7 +5663,7 @@ both here. - + Ou&tput: @@ -5881,67 +5902,67 @@ and DX Grid fields when a 73 or free text message is sent. - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> - + Accept UDP requests - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> - + Notify on accepted UDP request - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> - + Accepted UDP request restores window - + Secondary UDP Server (deprecated) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> - + Enable logged contact ADIF broadcast - + Server name or IP address: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> - + Server port number: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> @@ -6384,63 +6405,63 @@ Right click for insert and delete options. main - + Another instance may be running - + try to remove stale lock file? - + Failed to create a temporary directory - - + + Path: "%1" - + Failed to create a usable temporary directory - + Another application may be locking the directory - + Failed to create data directory - + path: "%1" - + Shared memory error - + Unable to create shared memory segment - + Sub-process error - + Failed to close orphaned jt9 process diff --git a/translations/wsjtx_en_GB.ts b/translations/wsjtx_en_GB.ts index a082fb6d7..d51b44d29 100644 --- a/translations/wsjtx_en_GB.ts +++ b/translations/wsjtx_en_GB.ts @@ -369,75 +369,75 @@ Configuration::impl - - - + + + &Delete - - + + &Insert ... - + Failed to create save directory - + path: "%1% - + Failed to create samples directory - + path: "%1" - + &Load ... - + &Save as ... - + &Merge ... - + &Reset - + Serial Port: - + Serial port used for CAT control - + Network Server: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -447,12 +447,12 @@ Formats: - + USB Device: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -460,156 +460,162 @@ Format: - - + + Invalid audio input device - + Invalid audio output device - + Invalid PTT method - + Invalid PTT port - - + + Invalid Contest Exchange - + You must input a valid ARRL Field Day exchange - + You must input a valid ARRL RTTY Roundup exchange - + Reset Decode Highlighting - + Reset all decode highlighting and priorities to default values - + WSJT-X Decoded Text Font Chooser - + Load Working Frequencies - - - + + + Frequency files (*.qrg);;All files (*.*) - + Replace Working Frequencies - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? - + Merge Working Frequencies - - - + + + Not a valid frequencies file - + Incorrect file magic - + Version is too new - + Contents corrupt - + Save Working Frequencies - + Only Save Selected Working Frequencies - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. - + Reset Working Frequencies - + Are you sure you want to discard your current working frequencies and replace them with default ones? - + Save Directory - + AzEl Directory - + Rig control error - + Failed to open connection to rig - + Rig failure + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1420,22 +1426,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency - + IARU &Region: - + &Mode: - + &Frequency (MHz): @@ -1554,180 +1560,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error - + Hamlib settings file error: %1 at character offset %2 - + Hamlib settings file error: top level must be a JSON object - + Hamlib settings file error: config must be a JSON object - + Unsupported CAT type - + Hamlib error: %1 while %2 - + opening connection to rig - + getting current frequency - + getting current mode - - + + exchanging VFOs - - + + getting other VFO frequency - + getting other VFO mode - - + + setting current VFO - + getting frequency - + getting mode - - - + + + getting current VFO - - - - + + + + getting current VFO frequency - - - - - - + + + + + + setting frequency - - - - + + + + getting current VFO mode - - - - - + + + + + setting current VFO mode - - + + setting/unsetting split mode - - + + setting split mode - + setting split TX frequency and mode - + setting split TX frequency - + getting split TX VFO mode - + setting split TX VFO mode - + getting PTT state - + setting PTT on - + setting PTT off - + setting a configuration item - + getting a configuration item @@ -2027,296 +2033,316 @@ Error(%2): %3 - - - - - - - - + + + + + + + + Band Activity - - + + UTC dB DT Freq Dr - - - - - - - + + + + + + + Rx Frequency - + CQ only - + Enter this QSO in log - + Log &QSO - + Stop monitoring - + &Stop - + Toggle monitoring On/Off - + &Monitor - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> - + Erase right window. Double-click to erase both windows. - + &Erase - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> - + Clear the accumulating message average. - + Clear Avg - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> - + Decode most recent Rx period at QSO Frequency - + &Decode - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> - + Toggle Auto-Tx On/Off - + E&nable Tx - + Stop transmitting immediately - + &Halt Tx - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> - + Toggle a pure Tx tone On/Off - + &Tune - + Menus - + + F High + + + + + F Low + + + + 1/2 - + 2/2 - + 1/3 - + 2/3 - + 3/3 - + 1/4 - + 2/4 - + 3/4 - + 4/4 - + 1/5 - + 2/5 - + 3/5 - + 4/5 - + 5/5 - + 1/6 - + 2/6 - + 3/6 - + 4/6 - + 5/6 - + 6/6 - + Percentage of minute sequences devoted to transmitting. - + Prefer Type 1 messages - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> - + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + + + USB dial frequency - + 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> - + Rx Signal - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2324,626 +2350,626 @@ Yellow when too low - + DX Call - + DX Grid - + Callsign of station to be worked - + Search for callsign in database - + &Lookup - + Locator of station to be worked - + Az: 251 16553 km - + Add callsign and locator to database - + Add - + Pwr - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. - + ? - + Adjust Tx audio level - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> - + Frequency entry - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. - + Hold Tx Freq - + Audio Rx frequency - - - - - + + + + + Hz - - + + Rx - - + + Set Tx frequency to Rx Frequency - + - + Frequency tolerance (Hz) - - + + F Tol - - + + Set Rx frequency to Tx Frequency - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. - + Sync - + <html><head/><body><p>Check to use short-format messages.</p></body></html> - + Check to use short-format messages. - + Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> - + Check to enable JT9 fast modes - - + + Fast - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. - + Auto Seq - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> - + Check to call the first decoded responder to my CQ. - + Call 1st - + Check to generate "@1250 (SEND MSGS)" in Tx6. - + Tx6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. - + Tx even/1st - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> - + Frequency to call CQ on in kHz above the current MHz - + Tx CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. - + Rx All Freqs - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> - + Submode determines tone spacing; A is narrowest. - + Submode - - + + Fox - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> - + Check to monitor Sh messages. - + SWL - + Best S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. - + Measure - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). - + Report - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> - + Tx/Rx or Frequency calibration sequence length - - + + s - - + + T/R - + Toggle Tx mode - + Tx JT9 @ - + Audio Tx frequency - - + + Tx - + Tx# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> - + Double-click on another caller to queue that call for your next QSO. - + Next Call - + 1 - - - + + + Send this message in next Tx interval - + Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - + Ctrl+1 - - - - + + + + Switch to this Tx message NOW - + Tx &2 - + Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) - + Tx &1 - + Alt+1 - + Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message - + Ctrl+5 - + Ctrl+3 - + Tx &3 - + Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required - + Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required - + Tx &4 - + Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message - + Tx &5 - + Alt+5 - + Now - + Generate standard messages for minimal QSO - + Generate Std Msgs - + Tx &6 - + Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2951,839 +2977,839 @@ list. The list can be maintained in Settings (F2). - + Queue up the next Tx message - + Next - + 2 - + Quick-Start Guide to FST4 and FST4W - + FST4 - + FST4W - - + + CQ - + Grid - + Max dB - + CQ AF - + CQ AN - + CQ AS - + CQ EU - + CQ NA - + CQ OC - + CQ SA - + CQ 0 - + CQ 1 - + CQ 2 - + CQ 3 - + CQ 4 - + CQ 5 - + CQ 6 - + CQ 7 - + CQ 8 - + CQ 9 - + Reset - + N List - + N Slots - - - - - - - + + + + + + + Random - + Call - + S/N (dB) - + Distance - + More CQs - - + + % - + Tx Pct - + Band Hopping - + Choose bands and times of day for band-hopping. - + Schedule ... - + Upload decoded messages to WSPRnet.org. - + Upload spots - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. - + No own call decodes - + Tx Next - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. - + NB - + File - + View - + Decode - + Save - + Help - + Mode - + Configurations - + Tools - + Exit - + About WSJT-X - + Waterfall - + Open - + Ctrl+O - + Open next in directory - + Decode remaining files in directory - + Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir - + None - + Save all - + Online User Guide - + Keyboard shortcuts - + Special mouse commands - + JT9 - + Save decoded - + Normal - + Deep - + Erase ALL.TXT - + Erase wsjtx_log.adi - + F7 - + Runaway Tx watchdog - + JT65 - + JT9+JT65 - + Astronomical data - + List of Type 1 prefixes and suffixes - + Settings... - + Local User Guide - + Open log directory - + JT4 - + Message averaging - + Enable averaging - + Enable deep search - + WSPR - + Echo Graph - + F8 - + Echo - + EME Echo mode - + ISCAT - + Fast Graph - + F9 - + &Download Samples ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> - + MSK144 - + QRA64 - + Release Notes - + Enable AP for DX Call - + FreqCal - + Measure reference spectrum - + Measure phase response - + Erase reference spectrum - + Execute frequency calibration cycle - + Equalization tools ... - + FT8 - - + + Enable AP - + Solve for calibration parameters - + Copyright notice - + Shift+F1 - + Fox log - + FT8 DXpedition Mode User Guide - + Reset Cabrillo log ... - + Color highlighting scheme - + Export Cabrillo log ... - + Contest log - + Erase WSPR hashtable - + FT4 - + Rig Control Error - - - + + + Receiving - + Do you want to reconfigure the radio interface? - + %1 (%2 sec) audio frames dropped - + Audio Source - + Reduce system load - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Error Scanning ADIF Log - + Scanned ADIF log, %1 worked before records created - + Error Loading LotW Users Data - + Error Writing WAV File - + Enumerating audio devices - + Configurations... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message - + Error Killing jt9.exe Process - + KillByName return code: %1 - + Error removing "%1" - + Click OK to retry - - + + Improper mode - - + + File Open Error - - - - - + + + + + Cannot open "%1" for append: %2 - + Error saving c2 file - + Error in Sound Input - + Error in Sound Output - - - + + + Single-Period Decodes - - - + + + Average Decodes - + Change Operator - + New operator: - + Status File Error - - + + Cannot open "%1" for writing: %2 - + Subprocess Error - + Subprocess failed with exit code %1 - + Running: %1 %2 - + Subprocess error - + Reference spectrum saved - + Invalid data in fmt.all at line %1 - + Good Calibration Solution - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -3792,44 +3818,44 @@ list. The list can be maintained in Settings (F2). - + Delete Calibration Measurements - + The "fmt.all" file will be renamed as "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - + No data read from disk. Wrong file format? - + Confirm Delete - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? - + Keyboard Shortcuts - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -3879,12 +3905,12 @@ list. The list can be maintained in Settings (F2). - + Special Mouse Commands - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -3920,42 +3946,42 @@ list. The list can be maintained in Settings (F2). - + No more files to open. - + Spotting to PSK Reporter unavailable - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. - + WSPR Guard Band - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. - + Fox Mode warning - + Last Tx: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -3963,176 +3989,176 @@ To do so, check 'Special operating activity' and - + Should you switch to ARRL Field Day mode? - + Should you switch to RTTY contest mode? - - - - + + + + Add to CALL3.TXT - + Please enter a valid grid locator - + Cannot open "%1" for read/write: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? - + Warning: DX Call field is empty. - + Log file error - + Cannot open "%1" - + Error sending log to N1MM - + Write returned "%1" - + Stations calling DXpedition %1 - + Hound - + Tx Messages - - - + + + Confirm Erase - + Are you sure you want to erase file ALL.TXT? - - + + Confirm Reset - + Are you sure you want to erase your contest log? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. - + Cabrillo Log saved - + Are you sure you want to erase file wsjtx_log.adi? - + Are you sure you want to erase the WSPR hashtable? - + Tune digital gain - + Transmit digital gain - + Prefixes - + Network Error - + Error: %1 UDP server %2:%3 - + File Error - + Phase Training Disabled - + Phase Training Enabled - + WD:%1m - - + + Log File Error - + Are you sure you want to clear the QSO queues? @@ -4465,22 +4491,17 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. - + An error occurred during read from the audio input device. - - Audio data not being fed to the audio input device fast enough. - - - - + Non-recoverable error, audio input device not usable at this time. @@ -4495,37 +4516,37 @@ Error(%2): %3 - + Failed to initialize audio sink device - + Idle - + Receiving - + Suspended - + Interrupted - + Error - + Stopped @@ -4533,67 +4554,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. - + An error occurred during write to the audio output device. - + Audio data not being fed to the audio output device fast enough. - + Non-recoverable error, audio output device not usable at this time. - + Requested output audio format is not valid. - + Requested output audio format is not supported on device. - + No audio output device configured. - + Idle - + Sending - + Suspended - + Interrupted - + Error - + Stopped @@ -4601,22 +4622,22 @@ Error(%2): %3 StationDialog - + Add Station - + &Band: - + &Offset (MHz): - + &Antenna: @@ -5556,7 +5577,7 @@ radio interface behave as expected. - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -5570,46 +5591,46 @@ transmitting periods. - + Select the audio CODEC to use for receiving. - + &Input: - + Select the channel to use for receiving. - - + + Mono - - + + Left - - + + Right - - + + Both - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -5622,7 +5643,7 @@ both here. - + Ou&tput: @@ -5846,67 +5867,67 @@ and DX Grid fields when a 73 or free text message is sent. - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> - + Accept UDP requests - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> - + Notify on accepted UDP request - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> - + Accepted UDP request restores window - + Secondary UDP Server (deprecated) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> - + Enable logged contact ADIF broadcast - + Server name or IP address: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> - + Server port number: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> @@ -6384,63 +6405,63 @@ Right click for insert and delete options. main - + Another instance may be running - + try to remove stale lock file? - + Failed to create a temporary directory - - + + Path: "%1" - + Failed to create a usable temporary directory - + Another application may be locking the directory - + Failed to create data directory - + path: "%1" - + Shared memory error - + Unable to create shared memory segment - + Sub-process error - + Failed to close orphaned jt9 process diff --git a/translations/wsjtx_es.ts b/translations/wsjtx_es.ts index ce89139ac..b6676a3a1 100644 --- a/translations/wsjtx_es.ts +++ b/translations/wsjtx_es.ts @@ -404,81 +404,81 @@ Configuration::impl - - - + + + &Delete &Borrar - - + + &Insert ... &Introducir ... &Agregar... - + Failed to create save directory No se pudo crear el directorio para guardar No se pudo crear el directorio "Save" - + path: "%1% ruta: "%1% - + Failed to create samples directory No se pudo crear el directorio de ejemplos No se pudo crear el directorio "Samples" - + path: "%1" ruta: "%1" - + &Load ... &Carga ... &Cargar ... - + &Save as ... &Guardar como ... &Guardar como ... - + &Merge ... &Fusionar ... &Fusionar ... - + &Reset &Reiniciar - + Serial Port: Puerto Serie: - + Serial port used for CAT control Puerto serie utilizado para el control CAT - + Network Server: Servidor de red: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -499,12 +499,12 @@ Formatos: [dirección IPv6]:port - + USB Device: Dispositivo USB: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -519,8 +519,8 @@ Formato: [VID[:PID[:VENDOR[:PRODUCT]]]] - - + + Invalid audio input device El dispositivo de entrada de audio no es válido Dispositivo de entrada de audio no válido @@ -531,172 +531,173 @@ Formato: Dispositivo de salida de audio no válido - + Invalid audio output device Dispositivo de salida de audio no válido - + Invalid PTT method El método de PTT no es válido Método PTT no válido - + Invalid PTT port El puerto del PTT no es válido Puerto PTT no válido - - + + Invalid Contest Exchange Intercambio de concurso no válido - + You must input a valid ARRL Field Day exchange Debes introducir un intercambio de Field Day del ARRL válido Debe introducir un intercambio válido para el ARRL Field Day - + You must input a valid ARRL RTTY Roundup exchange Debes introducir un intercambio válido de la ARRL RTTY Roundup Debe introducir un intercambio válido para el ARRL RTTY Roundup - + Reset Decode Highlighting Restablecer Resaltado de Decodificación Restablecer resaltado de colores de decodificados - + Reset all decode highlighting and priorities to default values Restablecer todo el resaltado y las prioridades de decodificación a los valores predeterminados Restablecer todo el resaltado de colores y prioridades a los valores predeterminados - + WSJT-X Decoded Text Font Chooser Tipo de texto de pantalla de descodificación WSJT-X Seleccionar un tipo de letra - + Load Working Frequencies Carga las frecuencias de trabajo Cargar las frecuencias de trabajo - - - + + + Frequency files (*.qrg);;All files (*.*) Archivos de frecuencia (*.qrg);;Todos los archivos (*.*) - + Replace Working Frequencies Sustituye las frecuencias de trabajo Sustituir las frecuencias de trabajo - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? ¿Seguro que quieres descartar tus frecuencias actuales de trabajo y reemplazarlas por las cargadas? ¿Seguro que quiere descartar las frecuencias de trabajo actuales y reemplazarlas por las cargadas? - + Merge Working Frequencies Combinar las frecuencias de trabajo Combina las frecuencias de trabajo - - - + + + Not a valid frequencies file El archivo de frecuencias no es válido Archivo de frecuencias no válido - + Incorrect file magic Archivo mágico incorrecto - + Version is too new La versión es demasiado nueva - + Contents corrupt contenidos corruptos Contenido corrupto - + Save Working Frequencies Guardar las frecuencias de trabajo - + Only Save Selected Working Frequencies Guarda sólo las frecuencias de trabajo seleccionadas Sólo guarda las frecuencias de trabajo seleccionadas - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. ¿Seguro que quieres guardar sólo las frecuencias de trabajo seleccionadas actualmente? Haz clic en No para guardar todo. ¿Seguro que quiere guardar sólo las frecuencias de trabajo seleccionadas actualmente? Clic en No para guardar todo. - + Reset Working Frequencies Reiniciar las frecuencias de trabajo - + Are you sure you want to discard your current working frequencies and replace them with default ones? ¿Seguro que quieres descartar tus frecuencias actuales de trabajo y reemplazarlas por otras? ¿Seguro que quiere descartar las frecuencias de trabajo actuales y reemplazarlas por las de defecto? - + Save Directory Guardar directorio Directorio "Save" - + AzEl Directory Directorio AzEl - + Rig control error Error de control del equipo - + Failed to open connection to rig No se pudo abrir la conexión al equipo Fallo al abrir la conexión al equipo - + Rig failure Fallo en el equipo + Not found audio device missing - No encontrado + No encontrado @@ -1591,23 +1592,23 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency Agregar frecuencia Añadir frecuencia - + IARU &Region: &Región IARU: - + &Mode: &Modo: - + &Frequency (MHz): &Frecuencia en MHz: &Frecuencia (MHz): @@ -1738,201 +1739,201 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Error de inicialización de Hamlib - + Hamlib settings file error: %1 at character offset %2 Error de archivo de configuración de Hamlib:%1 en el desplazamiento de caracteres %2 Error en archivo de configuración de Hamlib:%1 en el desplazamiento de caracteres %2 - + Hamlib settings file error: top level must be a JSON object Error en archivo de configuración de Hamlib: el nivel superior debe ser un objeto JSON Error de archivo de configuración de Hamlib: el nivel superior debe ser un objeto JSON - + Hamlib settings file error: config must be a JSON object Error de archivo de configuración de Hamlib: config debe ser un objeto JSON Error en archivo de configuración de Hamlib: config debe ser un objeto JSON - + Unsupported CAT type Tipo CAT no admitido - + Hamlib error: %1 while %2 Error Hamlib: %1 mientras %2 - + opening connection to rig conexión de apertura al equipo abriendo conexión al equipo - + getting current frequency obteniendo frecuencia actual - + getting current mode obteniendo el modo actual obteniendo modo actual - - + + exchanging VFOs intercambiando VFO's - - + + getting other VFO frequency obteniendo otra frecuencia de VFO obteniendo la frecuencia del otro VFO - + getting other VFO mode obteniendo otro modo VFO obteniendo modo del otro VFO - - + + setting current VFO ajuste al VFO actual ajustando VFO actual - + getting frequency obteniendo frecuencia - + getting mode obteniendo modo - - - + + + getting current VFO obteniendo el VFO actual obteniendo VFO actual - - - - + + + + getting current VFO frequency obteniendo la frecuencia actual de VFO obteniendo frecuencia del VFO actual - - - - - - + + + + + + setting frequency ajuste de frecuencia ajustando frecuencia - - - - + + + + getting current VFO mode obteniendo modo del VFO actual - - - - - + + + + + setting current VFO mode ajuste del modo VFO actual ajustando modo del VFO actual - - + + setting/unsetting split mode activación/desactivación del modo dividido (split) activar/desactivar modo "Split" - - + + setting split mode activar modo dividido (split) ajustando modo "Split" - + setting split TX frequency and mode Ajuste de frecuencia y modo de transmisión dividida (split) ajustando la frecuencia de TX y modo del "Split" - + setting split TX frequency ajuste de frecuencia dividida en TX ajustando frecuencia de TX del "Split" - + getting split TX VFO mode obteniendo el modo dividido de TX en el VFO obteniendo modo del VFO de TX en "Split" - + setting split TX VFO mode ajuste del modo dividido (split) en TX del VFO ajustando modo del VFO de TX en "Split" - + getting PTT state obteniendo el estado del PTT - + setting PTT on activar el PTT activando PTT - + setting PTT off desactivar el PTT desactivando PTT - + setting a configuration item activar un elemento de configuración ajustando un elemento de configuración - + getting a configuration item obteniendo un elemento de configuración @@ -2281,312 +2282,332 @@ Error(%2): %3 WSJT-X por K1JT - - - - - - - - + + + + + + + + Band Activity Actividad en la banda - - + + UTC dB DT Freq Dr UTC dB DH Freq Dr - - - - - - - + + + + + + + Rx Frequency Frecuencia de RX - + CQ only Solo CQ - + Enter this QSO in log Entra este QSO al log Guarda este QSO en el log - + Log &QSO Guardar QSO (&Q) - + Stop monitoring Deja de monitorizar Detener la monitorización - + &Stop Detener (&S) - + Toggle monitoring On/Off Activar/desactivar la monitorización Activa/Desactiva la monitorización - + &Monitor Monitor (&M) - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>Borrar ventana derecha. Haz doble clic para borrar ambas ventanas.</p></body></html> <html><head/><body><p>Clic para borrar ventana derecha.</p><p> Doble clic para borrar ambas ventanas.</p></body></html> - + Erase right window. Double-click to erase both windows. Borrar ventana derecha. Haz doble clic para borrar ambas ventanas. Borra ventana derecha. Doble clic para borrar ambas ventanas. - + &Erase Borrar (&E) - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body><p>Borrar el promedio de mensajes acumulados.</p></body></html> <html><head/><body><p>Borrar el promedio de mensajes acumulados.</p></body></html> - + Clear the accumulating message average. Borrar el promedio de mensajes acumulados. - + Clear Avg Borrar media - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body><p>Decodificar el período de RX más reciente en la frecuencia QSO</p></body></html> <html><head/><body><p>Decodifica el período de RX más reciente en la frecuencia del QSO</p></body></html> - + Decode most recent Rx period at QSO Frequency Decodificar el período de RX más reciente en la frecuencia QSO Decodifica el período más reciente de RX en la frecuencia del QSO - + &Decode &Decodificar Decodifica (&D) - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body><p>Activar/desactivar TX</p></body></html> <html><head/><body><p>Activar/Desactivar TX</p></body></html> - + Toggle Auto-Tx On/Off Activar/desactivar TX Activa/Desactiva Auto-TX - + E&nable Tx Activar TX (&N) - + Stop transmitting immediately Detiene TX inmediatamente Detener TX inmediatamente - + &Halt Tx Detener TX (&H) - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>Activar/desactivar un tono de transmisión puro</p></body></html> <html><head/><body><p>Activa/Desactiva la transmisión de un tono continuo</p></body></html> - + Toggle a pure Tx tone On/Off Activar/desactivar un tono de transmisión puro Activar/Desactivar TX con tono continuo - + &Tune Tono TX (&T) - + Menus Menús - + + F High + + + + + F Low + + + + 1/2 1/2 - + 2/2 2/2 - + 1/3 1/3 - + 2/3 2/3 - + 3/3 3/3 - + 1/4 1/4 - + 2/4 2/4 - + 3/4 3/4 - + 4/4 4/4 - + 1/5 1/5 - + 2/5 2/5 - + 3/5 3/5 - + 4/5 4/5 - + 5/5 5/5 - + 1/6 1/6 - + 2/6 2/6 - + 3/6 3/6 - + 4/6 4/6 - + 5/6 5/6 - + 6/6 6/6 - + Percentage of minute sequences devoted to transmitting. Porcentaje de minutos dedicados a transmisión. - + Prefer Type 1 messages Preferir mensajes tipo 1 - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>Transmitir durante la siguiente secuencia.</p></body></html> - + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + + + USB dial frequency Frecuencia de dial USB - + 14.078 000 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body><p>30dB recomendado cuando solo hay ruido presente,<br/>Verde cuando el nivel es bueno,<br/>Rojo cuando puede ocurrir recortes y<br/>Amarillo cuando esta muy bajo.</p></body></html> <html><head/><body><p>30 dB recomendado cuando solo hay ruido presente.<br>Verde: Nivel de audio aceptable.<br>Rojo: Pueden ocurrir fallos de audio.<br>Amarillo: Nivel de audio muy bajo.</p></body></html> - + Rx Signal Señal de RX Señal RX - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2601,321 +2622,321 @@ Rojo pueden ocurrir fallos de audio Amarillo cuando esta muy bajo. - + NB NB - + DX Call Indicativo DX - + DX Grid Locator/Grid DX Locator DX - + Callsign of station to be worked Indicativo de la estación a trabajar - + Search for callsign in database Buscar el indicativo en la base de datos (CALL3.TXT) - + &Lookup Buscar - + Locator of station to be worked Locator/Grid de la estación a trabajar Locator de la estación a trabajar - + Az: 251 16553 km Az: 251 16553 km - + Add callsign and locator to database Agregar indicativo y locator/Grid a la base de datos Agregar indicativo y locator a la base de datos (CALL3.TXT) - + Add Agregar - + Pwr Potencia - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body><p>Si ha habido un error en el control del equipo, haz clic para restablecer y leer la frecuencia del dial. S implica modo dividido o split.</p></body></html> <html><head/><body><p>Si está naranja o rojo, ha habido un error en el control del equipo</p><p>Clic para reiniciar y leer la frecuencia del dial. </p><p>S indica modo "Split".</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. Si ha habido un error en el control del equipo, haz clic para restablecer y leer la frecuencia del dial. S implica modo dividido o split. Si está naranja o rojo, ha habido un error en el control del equipo, clic para restablecer y leer la frecuencia del dial. S indica "Split". - + ? ? - + Adjust Tx audio level Ajuste del nivel de audio de TX Ajustar nivel de audio de TX - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body><p>Selecciona la banda operativa, introduce la frecuencia en MHz o introduce el incremento de kHz seguido de k.</p></body></html> <html><head/><body><p>Selecciona la banda, o escriba la frecuencia en MHz o escriba el incremento en kHz seguido de k.</p></body></html> - + Frequency entry Frecuencia de entrada - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. Selecciona la banda operativa, introduce la frecuencia en MHz o introduce el incremento de kHz seguido de k. Selecciona la banda o introduce la frecuencia en MHz o ecribe el incremento en kHz seguido de la letra k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body><p>Marca para mantener fija la frecuencia de transmisión al hacer doble clic en el texto decodificado.</p></body></html> <html><head/><body><p>Marcar para mantener fija la frecuencia de TX al hacer doble clic en el texto decodificado.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. Marca para mantener fija la frecuencia de transmisión al hacer doble clic en el texto decodificado. Marcar para mantener fija la frecuencia de TX al hacer doble clic en un texto decodificado. - + Hold Tx Freq Mantén TX Freq Mantener Frec. TX - + Audio Rx frequency Frecuencia de audio en RX Frecuencia de RX - - - - - + + + + + Hz Hz - - + + Rx RX - - + + Set Tx frequency to Rx Frequency Coloca la frecuencia de RX en la de TX Coloca la frecuencia de TX en la de RX - + - + Frequency tolerance (Hz) Frecuencia de tolerancia (Hz) - - + + F Tol F Tol - - + + Set Rx frequency to Tx Frequency Coloca la frecuencia de TX en la de RX Coloca la frecuencia de RX en la de TX - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body><p>Umbral de sincronización. Los números más bajos aceptan señales de sincronización más débiles.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. Umbral de sincronización. Los números más bajos aceptan señales de sincronización más débiles. - + Sync Sinc - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>Marca para usar mensajes de formato corto.</p></body></html> <html><head/><body><p>Marcar para usar mensajes de formato corto.</p></body></html> - + Check to use short-format messages. Marcar para usar mensajes de formato corto. Marca para usar mensajes de formato corto. - + Sh Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>Marca para habilitar los modos rápidos JT9</p></body></html> <html><head/><body><p>Marcar para habilitar los modos rápidos JT9</p></body></html> - + Check to enable JT9 fast modes Marca para habilitar los modos rápidos JT9 Marcar para habilitar los modos rápidos JT9 - - + + Fast Rápido - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body><p>Marca para habilitar la secuencia automática de mensajes de TX en función de los mensajes recibidos.</p></body></html> <html><head/><body><p>Marcar para habilitar la secuencia automática de mensajes de TX en función de los mensajes recibidos.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. Marca para habilitar la secuencia automática de mensajes de TX en función de los mensajes recibidos. Marcar para habilitar la secuencia automática de mensajes de TX en función de los mensajes recibidos. - + Auto Seq Secuencia Automática Secuencia Auto. - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body><p>Responde al 1er. CQ decodificado.</p></body></html> <html><head/><body><p>Marcar para responder a la 1ra estación decodificada.</p></body></html> - + Check to call the first decoded responder to my CQ. Responde al 1er. CQ decodificado. Marcar para responder al 1ra. estación decodificada. - + Call 1st Responde al 1er. CQ 1er decodificado - + Check to generate "@1250 (SEND MSGS)" in Tx6. Marcar para generar "@1250 (SEND MSGS)" en TX6. - + Tx6 TX6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body><p>Marca a TX en minutos o secuencias de números pares, a partir de 0; desmarca las secuencias impares.</p></body></html> <html><head/><body><p>Marcar para transmitir en secuencias o minutos pares, comenzando por 0; desmarca para transmitir en las secuencias o minutos impares.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. Marca a TX en minutos o secuencias de números pares, a partir de 0; desmarca las secuencias impares. Marcar para transmitir en secuencias o minutos pares, comenzando por 0; desmarca para transmitir en las secuencias o minutos impares. - + Tx even/1st Alternar periodo TX Par/Impar TX segundo par - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body><p>Frecuencia para llamar a CQ en kHz por encima del MHz actual</p></body></html> <html><head/><body><p>Frecuencia para llamar CQ en kHz por sobre el MHz actual</p></body></html> - + Frequency to call CQ on in kHz above the current MHz Frecuencia para llamar a CQ en kHz por encima del MHz actual Frecuencia para llamar CQ en kHz por encima del MHz actual - + Tx CQ TX CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body><p>Marca esto para llamar a CQ en la frecuencia&quot;TX CQ&quot;. RX será a la frecuencia actual y el mensaje CQ incluirá la frecuencia de RX actual para que los corresponsales sepan en qué frecuencia responder.</p><p>No está disponible para los titulares de indicativo no estándar.</p></body></html> <html><head/><body><p>Marcar para llamar CQ en la frecuencia "TX CQ". RX será a la frecuencia actual y el mensaje CQ incluirá la frecuencia de RX actual para que los corresponsales sepan en qué frecuencia responder.</p><p>No está disponible para los titulares de indicativo no estándar.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. Marca esto para llamar a CQ en la frecuencia "TX CQ". RX será a la frecuencia actual y el mensaje CQ incluirá la frecuencia de RX actual para que los corresponsales sepan en qué frecuencia responder. @@ -2923,63 +2944,63 @@ No está disponible para los titulares de indicativo no estándar.Marcar para llamar CQ en la frecuencia "TX CQ". RX será a la frecuencia actual y el mensaje CQ incluirá la frecuencia de RX actual para que los corresponsales sepan en qué frecuencia responder. No está disponible para los titulares de indicativo no estándar. - + Rx All Freqs RX en todas las frecuencias - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body><p>El submodo determina el espaciado de tono; "A" es más estrecho.</p></body></html> - + Submode determines tone spacing; A is narrowest. El submodo determina el espaciado de tono; "A" es más estrecho. - + Submode Submodo - - + + Fox Fox "Fox" - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>Marca para monitorear los mensajes Sh.</p></body></html> <html><head/><body><p>Marcar para escuchar los mensajes Sh.</p></body></html> - + Check to monitor Sh messages. Marca para monitorear los mensajes Sh. Marcar para escuchar los mensajes Sh. - + SWL SWL - + Best S+P El mejor S+P Mejor S+P (&B) - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body><p>Marca para comenzar a registrar los datos de calibración.<br/>Mientras se mide la corrección de calibración, se desactiva.<br/>Cuando no está marcado, puedes ver los resultados de la calibración.</p></body></html> <html><head/><body><p>Marcar para comenzar a grabar los datos de calibración.<br/>Mientras se mide, la corrección de calibración está desactivada.<br/>Cuando no está marcado, puede verse los resultados de la calibración.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2991,123 +3012,123 @@ Mientras se mide, la corrección de calibración está desactivada. Cuando no está marcado, puede verse los resultados de la calibración. - + Measure Medida - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body><p>Informe de señal: relación señal/ruido en ancho de banda de referencia de 2500 Hz (dB).</p></body></html> <html><head/><body><p>Reporte de señal: Relación señal/ruido en ancho de banda de referencia de 2500 Hz (dB).</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). Informe de señal: relación señal/ruido en ancho de banda de referencia de 2500 Hz (dB). Reporte de señal: Relación señal/ruido en ancho de banda de referencia de 2500 Hz (dB). - + Report No -> Señal de Recepción Reporte - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>Tx/Rx o longitud de secuencia de calibración de frecuencia</p></body></html> <html><head/><body><p>TX/RX o longitud de secuencia de calibración de frecuencia</p></body></html> - + Tx/Rx or Frequency calibration sequence length Tx/Rx o longitud de secuencia de calibración de frecuencia TX/RX o longitud de secuencia de calibración de frecuencia - - + + s s - - + + T/R T/R - + Toggle Tx mode Conmuta el modo TX Conmuta modo TX - + Tx JT9 @ TX JT9 @ - + Audio Tx frequency Frecuencia de audio de TX Frecuencia de TX - - + + Tx TX - + Tx# TX# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body><p>Haz doble clic en otro indicativo que llama para poner en la cola esa llamada para tú siguiente QSO.</p></body></html> <html><head/><body><p>Doble clic en otra estación llamando para poner en la cola ese indicativo para tu siguiente QSO.</p></body></html> - + Double-click on another caller to queue that call for your next QSO. Haz doble clic en otro indicativo que llama para poner en la cola esa llamada para tú siguiente QSO. Doble clic en otra estación llamando para poner en la cola ese indicativo para tu siguiente QSO. - + Next Call Siguiente Indicativo - + 1 1 - - - + + + Send this message in next Tx interval Enviar este mensaje en el siguiente intervalo de transmisión Enviar este mensaje en el siguiente intervalo de TX - + Ctrl+2 Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>Enviar este mensaje en el siguiente intervalo de transmisión.</p><p>Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</p></body></html> <html><head/><body><p>Enviar este mensaje en el siguiente intervalo de TX.</p><p>Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Enviar este mensaje en el siguiente intervalo de transmisión. @@ -3115,37 +3136,37 @@ Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una Enviar este mensaje en el siguiente intervalo de TX. Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1). - + Ctrl+1 Ctrl+1 - - - - + + + + Switch to this Tx message NOW Cambia a este mensaje de TX AHORA Cambiar a este mensaje de TX AHORA - + Tx &2 TX &2 - + Alt+2 Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>Cambia a este mensaje de TX AHORA.</p><p>Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</p></body></html> <html><head/><body><p>Cambiar a este mensaje de TX AHORA.</p><p>Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1).</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Cambia a este mensaje de TX AHORA. @@ -3153,78 +3174,78 @@ Haz doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una Cambiar a este mensaje de TX AHORA.Doble clic para alternar el uso del mensaje TX1 para iniciar un QSO con una estación (no está permitido para titulares de indicativos compuestos de tipo 1) - + Tx &1 Tx &1 - + Alt+1 Alt+1 - + Ctrl+6 Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Enviar este mensaje en el siguiente intervalo de transmisión</p><p>Haz doble clic para restablecer el mensaje estándar 73.</p></body></html> <html><head/><body><p>Enviar este mensaje en el siguiente intervalo de TX</p><p>Doble clic para restablecer el mensaje 73 estándar.</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message Enviar este mensaje en el siguiente intervalo de TX. Doble clic para restablecer el mensaje 73 estándar. - + Ctrl+5 Ctrl+5 - + Ctrl+3 Ctrl+3 - + Tx &3 TX &3 - + Alt+3 Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>Envia este mensaje en el siguiente intervalo de transmisión.</p><p>Haz doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).</p><p>Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</p></body></html> <html><head/><body><p>Envia este mensaje en el siguiente intervalo de TX.</p><p>Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).</p><p>Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required Envia este mensaje en el siguiente intervalo de TX. Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2). Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes - + Ctrl+4 Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>Cambia a este mensaje de TX AHORA.</p><p>Haz doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).</p><p>Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</p></body></html> <html><head/><body><p>Cambiar a este mensaje de TX AHORA.</p><p>Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2).</p><p>Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes.</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -3234,23 +3255,23 @@ Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no Cambiar a este mensaje de TX AHORA. Doble clic para alternar entre los mensajes RRR y RR73 en TX4 (no está permitido para titulares de indicativos compuestos de tipo 2). Los mensajes RR73 solo deben usarse cuando esté razonablemente seguro de que no se requerirán repeticiones de mensajes. - + Tx &4 TX &4 - + Alt+4 Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Cambia a este mensaje de TX AHORA.</p><p>Haz doble clic para restablecer el mensaje estándar 73.</p></body></html> <html><head/><body><p>Cambiar a este mensaje de TX AHORA.</p><p>Doble clic para restablecer el mensaje estándar 73.</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message Cambia a este mensaje de TX AHORA. @@ -3259,44 +3280,44 @@ Haz doble clic para restablecer el mensaje estándar 73. Doble clic para cambiar al mensaje estándar 73. - + Tx &5 TX &5 - + Alt+5 Alt+5 - + Now Ahora - + Generate standard messages for minimal QSO Genera mensajes estándar para un QSO mínimo Genera mensajes estándares para realizar un QSO - + Generate Std Msgs Genera Mensaje Standar Genera Mensajes Estándar - + Tx &6 TX &6 - + Alt+6 Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -3311,32 +3332,32 @@ Presiona INTRO para agregar el texto actual a la lista predefinida. La lista se puede modificar en "Ajustes" (F2). - + Queue up the next Tx message Poner en cola el siguiente mensaje de TX - + Next Siguiente - + 2 2 - + Quick-Start Guide to FST4 and FST4W Guía de inicio rápido a FST4 y FST4W - + FST4 FST4 - + FST4W FST4W @@ -3349,8 +3370,8 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Genera mensaje CQ - - + + CQ CQ @@ -3381,7 +3402,7 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Genera mensaje para responder a un CQ - + Grid Locator/grid Locator @@ -3428,138 +3449,138 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).3 - + Max dB Max dB - + CQ AF CQ AF - + CQ AN CQ AN - + CQ AS CQ AS - + CQ EU CQ EU - + CQ NA CQ NA - + CQ OC CQ OC - + CQ SA CQ SA - + CQ 0 CQ 0 - + CQ 1 CQ 1 - + CQ 2 CQ 2 - + CQ 3 CQ 3 - + CQ 4 CQ 4 - + CQ 5 CQ 5 - + CQ 6 CQ 6 - + CQ 7 CQ 7 - + CQ 8 CQ 8 - + CQ 9 CQ 9 - + Reset Reiniciar - + N List N List - + N Slots N Slots - - - - - - - + + + + + + + Random Aleatorio - + Call Indicativo - + S/N (dB) S/N (dB) - + Distance Distancia - + More CQs Más CQ's @@ -3568,53 +3589,53 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Porcentaje de secuencias de 2 minutos dedicadas a la transmisión. - - + + % % - + Tx Pct TX Pct Pct TX - + Band Hopping Salto de banda - + Choose bands and times of day for band-hopping. Elija bandas y momentos del día para saltar de banda. Escoja bandas y momentos del día para saltos de banda. - + Schedule ... Calendario ... Programar ... - + Upload decoded messages to WSPRnet.org. Cargue mensajes decodificados a WSPRnet.org. Subir mensajes decodificados a WSPRnet.org. - + Upload spots Subir "Spots" - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>Los Locator/Grid de 6 dígitos hacen que se envíen 2 mensajes diferentes, el segundo contiene el locator completo, pero sólo un indicativo troceado, las otras estaciones deben haber decodificado el primero una vez antes de poder descodificar el segundo. Marca esta opción para enviar sólo locators de 4 dígitos y se evitará el protocolo de dos mensajes.</p></body></html> <html><head/><body><p>Los locator de 6 dígitos hace que se envíen 2 mensajes diferentes, el segundo contiene el locator completo, pero sólo un indicativo, otras estaciones deben haber decodificado el primero antes de poder descodificar el segundo. Marcar esta opción para enviar sólo locators de 4 dígitos y se evitará el protocolo de dos mensajes.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. Los Locator/Grid de 6 dígitos hacen que se envíen 2 mensajes diferentes, el segundo contiene el locator completo, pero sólo un indicativo troceado, las otras estaciones deben haber decodificado el primero una vez antes de poder descodificar el segundo. Marca esta opción para enviar sólo locators de 4 dígitos y se evitará el protocolo de dos mensajes. Los locator de 6 dígitos hace que se envíen 2 mensajes diferentes, el segundo contiene el locator completo, pero sólo un indicativo, otras estaciones deben haber decodificado el primero antes de poder descodificar el segundo. Marcar esta opción para enviar sólo locators de 4 dígitos y se evitará el protocolo de dos mensajes. @@ -3625,7 +3646,7 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Preferir mensajes de tipo 1 - + No own call decodes No se descodifica ningún indicativo propio No se descodifica mi indicativo @@ -3635,60 +3656,60 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Transmite durante la siguiente secuencia de 2 minutos. - + Tx Next Siguiente TX - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. Configura la potencia de transmisión en dBm (dB por encima de 1 mW) como parte de tú mensaje WSPR. Configurar la potencia de TX en dBm (dB por encima de 1 mW) como parte de su mensaje WSPR. - + File Archivo - + View Ver - + Decode Decodifica Decodificar - + Save Guardar - + Help Ayuda - + Mode Modo - + Configurations No es valido utilizar Ajustes Configuraciones - + Tools Herramientas - + Exit Salir @@ -3701,91 +3722,91 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).F2 - + About WSJT-X Acerca de WSJT-X - + Waterfall Cascada Cascada (Waterfall) - + Open Abrir - + Ctrl+O Ctrl+O - + Open next in directory Abrir siguiente en el directorio - + Decode remaining files in directory Decodifica los archivos restantes en el directorio - + Shift+F6 Mayúsculas+F6 Mayúsculas+F6 - + Delete all *.wav && *.c2 files in SaveDir Borrar todos los archivos *.wav y *.c2 - + None Ninguno Nada - + Save all Guardar todo - + Online User Guide Guía de usuario en línea - + Keyboard shortcuts Atajos de teclado - + Special mouse commands Comandos especiales de ratón - + JT9 JT9 - + Save decoded Guarda el decodificado Guardar lo decodificado - + Normal Normal - + Deep Profundo @@ -3795,12 +3816,12 @@ predefinida. La lista se puede modificar en "Ajustes" (F2)."Monitor" apagado al inicio - + Erase ALL.TXT Borrar ALL.TXT - + Erase wsjtx_log.adi Borrar el archivo wsjtx_log.adi Borrar archivo wsjtx_log.adi @@ -3839,7 +3860,7 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Doble clic en el indicativo activa la TX - + F7 F7 @@ -3849,7 +3870,7 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Dehabilita TX después de enviar 73 - + Runaway Tx watchdog Temporizador de TX @@ -3863,12 +3884,12 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Freq. de TX bloqueda a freq. de RX - + JT65 JT65 - + JT9+JT65 JT9+JT65 @@ -3887,154 +3908,154 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Mostrar DXCC y estado B4 trabajado - + Astronomical data Datos astronómicos - + List of Type 1 prefixes and suffixes Lista de prefijos y sufijos de tipo 1 Lista de prefijos y sufijos tipo 1 - + Settings... Configuración Ajustes... - + Local User Guide Guía de usuario local - + Open log directory Abrir directorio de log - + JT4 JT4 - + Message averaging Promedio de mensajes - + Enable averaging Habilitar el promedio - + Enable deep search Habilitar búsqueda profunda - + WSPR WSPR - + Echo Graph Gráfico de eco - + F8 F8 - + Echo Echo Eco - + EME Echo mode Modo EME Eco - + ISCAT ISCAT - + Fast Graph Gráfico rápido "Fast Graph" - + F9 F9 - + &Download Samples ... &Descargar muestras ... &Descargar muestras de audio ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>Descarga archivos de audio de muestra que demuestren los distintos modos.</p></body></html> <html><head/><body><p>Descargar archivos de audio de los distintos modos.</p></body></html> - + MSK144 MSK144 - + QRA64 QRA64 - + Release Notes Cambios en la nueva versión - + Enable AP for DX Call Habilitar AP para llamada DX Habilitar AP para indicativo DX - + FreqCal FreqCal - + Measure reference spectrum Medir espectro de referencia - + Measure phase response Medir la respuesta de fase - + Erase reference spectrum Borrar espectro de referencia - + Execute frequency calibration cycle Ejecutar ciclo de calibración de frecuencia - + Equalization tools ... Herramientas de ecualización ... @@ -4047,51 +4068,51 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Modo experimental LF/MF - + FT8 FT8 - - + + Enable AP Habilitar AP - + Solve for calibration parameters Resolver para parámetros de calibración Resolver parámetros de calibración - + Copyright notice Derechos de Autor - + Shift+F1 Mayúsculas+F1 - + Fox log Log Fox Log "Fox" - + FT8 DXpedition Mode User Guide Guía de usuario del modo FT8 DXpedition (inglés) - + Reset Cabrillo log ... Restablecer log de Cabrillo ... Borrar log Cabrillo ... - + Color highlighting scheme Esquema de resaltado de color Esquema de resaltado de colores @@ -4101,7 +4122,7 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Log de Concurso - + Export Cabrillo log ... Exportar log de Cabrillo ... Exportar log Cabrillo ... @@ -4111,49 +4132,49 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Guía de inicio rápido para WSJT-X 2.0 (inglés) - + Contest log Log de Concurso - + Erase WSPR hashtable Borrar la tabla de WSPR - + FT4 FT4 - + Rig Control Error Error de control del equipo - - - + + + Receiving Recibiendo - + Do you want to reconfigure the radio interface? ¿Desea reconfigurar la interfaz de radio? - + %1 (%2 sec) audio frames dropped %1 (%2 seg) de audio rechazados - + Audio Source Origen del audio - + Reduce system load Reduzca la carga del sistema @@ -4162,179 +4183,179 @@ predefinida. La lista se puede modificar en "Ajustes" (F2).Excesiva muestras rechazadas - %1 (%2 seg) de audio rechazados - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 Excesiva muestras rechazadas - %1 (%2 seg) de audio rechazados en periodo %3 - + Error Scanning ADIF Log Error al escanear el log ADIF - + Scanned ADIF log, %1 worked before records created Log ADIF escaneado, %1 funcionaba antes de la creación de registros Log ADIF escaneado, %1 registros trabajados B4 creados - + Error Loading LotW Users Data Error al cargar datos de usuarios de LotW Error al cargar datos de usuarios de LoTW - + Error Writing WAV File Error al escribir el archivo WAV - + Enumerating audio devices Listando dispositivos de audio - + Configurations... Conmfiguraciones... Configuraciones... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message Mensaje - + Error Killing jt9.exe Process Error al matar el proceso jt9.exe - + KillByName return code: %1 Código de retorno de KillByName: %1 KillByName regresa código: %1 - + Error removing "%1" Error al eliminar "%1" - + Click OK to retry Haga clic en Aceptar para volver a intentar Clic en "Aceptar" para reintentar - - + + Improper mode Modo incorrecto - - + + File Open Error Error de apertura del archivo Error al abrir archivo - - - - - + + + + + Cannot open "%1" for append: %2 No puedo abrir "%1" para anexar: %2 No se puedo abrir "%1" para anexar: %2 - + Error saving c2 file Error al guardar el archivo c2 Error al guardar archivo c2 - + Error in Sound Input Error en entrada de sonido - + Error in Sound Output Error en la salida de sonido Error en salida de audio - - - + + + Single-Period Decodes Decodificaciones de un solo período - - - + + + Average Decodes Promedio de decodificaciones - + Change Operator Cambiar operador - + New operator: Nuevo operador: - + Status File Error Error de estado del archivo Error en el archivo de estado - - + + Cannot open "%1" for writing: %2 No se puede abrir "%1" para la escritura: %2 No se puede abrir "%1" para escritura: %2 - + Subprocess Error Error de subproceso - + Subprocess failed with exit code %1 El subproceso falló con el código de salida %1 - + Running: %1 %2 Corriendo: %1 @@ -4343,27 +4364,27 @@ Error al cargar datos de usuarios de LotW %2 - + Subprocess error Error de subproceso - + Reference spectrum saved Espectro de referencia guardado - + Invalid data in fmt.all at line %1 Datos no válidos en fmt.all en la línea %1 - + Good Calibration Solution Buena solución de calibración - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -4376,18 +4397,18 @@ Error al cargar datos de usuarios de LotW %9%L10 Hz</pre> - + Delete Calibration Measurements Eliminar mediciones de calibración Borrar mediciones de calibración - + The "fmt.all" file will be renamed as "fmt.bak" El archivo "fmt.all" será renombrado como "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -4399,31 +4420,31 @@ Error al cargar datos de usuarios de LotW "Los algoritmos, el código fuente, la apariencia y comportamiento del WSJT-X y los programas relacionados, y las especificaciones del protocolo para los modos FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 son Copyright (C) 2001-2020 por uno o más de los siguientes autores: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q y otros miembros del Grupo de Desarrollo WSJT ". - + No data read from disk. Wrong file format? No se leen datos del disco. Formato de archivo incorrecto? No se han leido datos del disco. Formato de archivo incorrecto? - + Confirm Delete Confirmar eliminación Confirmar borrado - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? ¿Estas seguro de que deseas eliminar todos los archivos *.wav y *.c2 en "%1"? ¿Esta seguro de que desea borrar todos los archivos *.wav y *.c2 en "%1"? - + Keyboard Shortcuts Atajo de teclado Atajos de teclado - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4610,13 +4631,13 @@ Error al cargar datos de usuarios de LotW </table> - + Special Mouse Commands Comandos especiales del ratón Comandos especiales de ratón - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4681,47 +4702,47 @@ Error al cargar datos de usuarios de LotW </table> - + No more files to open. No hay más archivos para abrir. - + Spotting to PSK Reporter unavailable "Spotting" a PSK Reporter no disponible - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. Por favor, elije otra frecuencia de transmisión. WSJT-X no transmitirá a sabiendas otro modo en la sub-banda WSPR en 30m. Elije otra frecuencia de transmisión. WSJT-X no transmitirá a sabiendas otro modo en la sub-banda WSPR en 30M. - + WSPR Guard Band Banda de Guardia WSPR WSPR protección de banda - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. Elige otra frecuencia de dial. WSJT-X no funcionará en modo Fox en las sub-bandas FT8 estándar. Por favor elija otra frecuencia. WSJT-X no operá en modo "Fox" en las sub-bandas de FT8 estándar. - + Fox Mode warning Advertencia del modo Fox Advertencia de modo "Fox" - + Last Tx: %1 Última TX: %1 Últ TX: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4736,37 +4757,37 @@ Para hacerlo, marca "Actividad operativa especial" y luego "Concurso VHF EU" en "Archivo" - "Ajustes" - "Avanzado". - + Should you switch to ARRL Field Day mode? ¿Cambiar al modo ARRL Field Day? - + Should you switch to RTTY contest mode? ¿Cambiar al modo de concurso RTTY? - - - - + + + + Add to CALL3.TXT Añadir a CALL3.TXT - + Please enter a valid grid locator Por favor, introduce un locator/Grid válido Por favor escriba un locator válido - + Cannot open "%1" for read/write: %2 No se puede abrir "%1" para leer/escribir: %2 No se puede abrir "%1" para lectura/escritura: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? %1 @@ -4775,97 +4796,97 @@ ya está en CALL3.TXT, ¿deseas reemplazarlo? ya está en CALL3.TXT, ¿desea reemplazarlo? - + Warning: DX Call field is empty. Advertencia: el campo de Indicativo DX está vacío. Advertencia: El campo "Indicativo DX" está vacío. - + Log file error Error de archivo de log Error en el archivo de log - + Cannot open "%1" No puedo abrir "%1" No se puede abrir "%1" - + Error sending log to N1MM Error al enviar el log a N1MM - + Write returned "%1" Escritura devuelta "%1" Escritura devuelve "%1" - + Stations calling DXpedition %1 Estaciones que llaman a DXpedition %1 Estaciones llamando a DXpedition %1 - + Hound Hound "Hound" - + Tx Messages Mensajes de TX Mensajes TX - - - + + + Confirm Erase Confirmar borrado - + Are you sure you want to erase file ALL.TXT? ¿Estás seguro de que quiere borrar el archivo ALL.TXT? - - + + Confirm Reset Confirmar reinicio Confirmar restablecer - + Are you sure you want to erase your contest log? ¿Estás seguro de que quieres borrar el log de tú concurso? ¿Está seguro que quiere borrar el log de concurso? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. Hacer esto eliminará todos los registros de QSO para el concurso actual. Se guardarán en el archivo log de ADIF, pero no estarán disponibles para la exportación en tú log de Cabrillo. Hacer esto eliminará todos los QSOs del concurso actual. Se mantendrán en el log ADIF, pero no estarán disponibles para la exportación como log de Cabrillo. - + Cabrillo Log saved Cabrillo Log guardado Log Cabrillo guardado - + Are you sure you want to erase file wsjtx_log.adi? ¿Estás seguro de que quieres borrar el archivo wsjtx_log.adi? ¿Está seguro que quiere borrar el archivo wsjtx_log.adi? - + Are you sure you want to erase the WSPR hashtable? ¿Estás seguro de que quieres borrar la tabla WSPR? ¿Está seguro de que quiere borrar la tabla hash WSPR? @@ -4875,66 +4896,66 @@ ya está en CALL3.TXT, ¿desea reemplazarlo? Advertencia de características VHF - + Tune digital gain Ganancia de sintonización digital Ajustar ganancia digital - + Transmit digital gain Ganancia de transmisión digital Transmitir ganancia digital - + Prefixes Prefijos Prefijos y sufijos tipo 1 - + Network Error Error de red - + Error: %1 UDP server %2:%3 Error: %1 Servidor UDP %2:%3 - + File Error Error en el archivo - + Phase Training Disabled Fase de entrenamiento deshabilitado Entrenamieno de Fase deshabilitado - + Phase Training Enabled Fase de entrenamiento habilitado Entrenamiento de Fase habilitado - + WD:%1m WD:%1m - - + + Log File Error Error de archivo log Error en archivo log - + Are you sure you want to clear the QSO queues? ¿Estás seguro de que quieres borrar las colas QSO? ¿Está seguro que quiere borrar las colas de QSOs? @@ -5310,23 +5331,22 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. Se produjo un error al abrir el dispositivo de entrada de audio. - + An error occurred during read from the audio input device. Se produjo un error durante la lectura desde el dispositivo de entrada de audio. Se produjo un error durante la lectura del dispositivo de entrada de audio. - Audio data not being fed to the audio input device fast enough. - Los datos de audio no se envían al dispositivo de entrada de audio lo suficientemente rápido. + Los datos de audio no se envían al dispositivo de entrada de audio lo suficientemente rápido. - + Non-recoverable error, audio input device not usable at this time. Error no recuperable, el dispositivo de entrada de audio no se puede utilizar en este momento. Error no recuperable, dispositivo de entrada de audio no disponible en este momento. @@ -5343,37 +5363,37 @@ Error(%2): %3 El formato de audio de entrada solicitado no está soportado en el dispositivo. - + Failed to initialize audio sink device Error al inicializar el dispositivo receptor de audio - + Idle Inactivo - + Receiving Recibiendo - + Suspended Suspendido - + Interrupted Interrumpido - + Error Error - + Stopped Detenido @@ -5381,67 +5401,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. Se produjo un error al abrir el dispositivo de salida de audio. - + An error occurred during write to the audio output device. Se produjo un error durante la escritura en el dispositivo de salida de audio. - + Audio data not being fed to the audio output device fast enough. Los datos de audio no se envían al dispositivo de salida de audio lo suficientemente rápido. - + Non-recoverable error, audio output device not usable at this time. Error no recuperable, dispositivo de salida de audio no utilizable en este momento. - + Requested output audio format is not valid. El formato de audio de salida solicitado no es válido. - + Requested output audio format is not supported on device. El formato de audio de salida solicitado no es compatible con el dispositivo. - + No audio output device configured. No hay dispositivo de salida de audio configurado - + Idle Inactivo - + Sending Recibiendo - + Suspended Suspendido - + Interrupted Interrumpido - + Error Error - + Stopped Detenido @@ -5449,23 +5469,23 @@ Error(%2): %3 StationDialog - + Add Station Agregar estación - + &Band: &Banda: - + &Offset (MHz): &Desplazamiento en MHz: Desplazamient&o (MHz): - + &Antenna: &Antena: @@ -6553,7 +6573,7 @@ interfaz de radio se comporte como se esperaba. Tarjeta de Sonido - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -6571,48 +6591,48 @@ de lo contrario transmitirá cualquier sonido del sistema generado durante los períodos de transmisión. - + Select the audio CODEC to use for receiving. Selecciona el CODEC de audio que se usará para recibir. Selecciona el CODEC a usar para recibir. - + &Input: &Entrada: - + Select the channel to use for receiving. Selecciona el canal a usar para recibir. Seleccione el canal a usar para recibir. - - + + Mono Mono - - + + Left Izquierdo - - + + Right Derecho - - + + Both Ambos - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -6632,7 +6652,7 @@ canales, entonces, generalmente debe seleccionar "Mono" o Habilitar funciones de VHF y submodo - + Ou&tput: &Salida: @@ -6921,72 +6941,72 @@ para evaluar la propagación y el rendimiento del sistema. <html><head/><body><p>Escriba el número del puerto del servidor UDP al que WSJT-X debe enviar actualizaciones. Si este es cero, no se transmitirán actualizaciones.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p>Con esto habilitado, WSJT-X aceptará ciertas solicitudes de un servidor UDP que recibe mensajes de decodificación.</p></body></html> <html><head/><body><p>Si se habilita, WSJT-X aceptará ciertas solicitudes de un servidor UDP que recibe mensajes decodificados.</p></body></html> - + Accept UDP requests Aceptar solicitudes UDP - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p>Indica la aceptación de una solicitud UDP entrante. El efecto de esta opción varía según el sistema operativo y el administrador de ventanas, su intención es notificar la aceptación de una solicitud UDP entrante, incluso si esta aplicación está minimizada u oculta.</p></body></html> <html><head/><body><p>Indica la aceptación de una solicitud UDP entrante. El efecto de esta opción varía según el sistema operativo y el "Window Manager", su intención es notificar la aceptación de una solicitud UDP entrante, incluso si esta aplicación está minimizada u oculta.</p></body></html> - + Notify on accepted UDP request Notificar sobre una solicitud UDP aceptada - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p>Restaura la ventana minimizada si se acepta una solicitud UDP.</p></body></html> - + Accepted UDP request restores window La solicitud UDP aceptada restaura la ventana Una solicitud UDP aceptada restaura la ventana - + Secondary UDP Server (deprecated) Servidor UDP secundario (en desuso) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p>Cuando se marca, WSJT-X transmitirá un contacto registrado en formato ADIF al nombre de host y puerto configurados. </p></body></html> <html><head/><body><p>Si se marca , WSJT-X difundirá el contacto guardado, en formato ADIF, al servidor y puerto configurados. </p></body></html> - + Enable logged contact ADIF broadcast Habilita la transmisión ADIF de contacto registrado Habilita "broadcast" de contacto guardado (ADIF) - + Server name or IP address: Nombre del servidor o dirección IP: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>"Hostname" del programa N1MM Logger + donde se recibirán las transmisiones ADIF UDP. Este suele ser 'localhost' o dirección IP 127.0.0.1</p><p>Formatos:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dirección IPv4</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dirección IPv6</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dirección IPv4 multicast</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Dirección IPv6 multicast</li></ul><p>Borrar este campo deshabilitará la transmisión de información ADIF a través de UDP.</p></body></html> - + Server port number: Número de puerto del servidor: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>Introduce el número de puerto que WSJT-X debe usar para las transmisiones UDP de información de registro ADIF. Para N1MM Logger +, este valor debe ser 2333. Si es cero, no se transmitirán actualizaciones.</p></body></html> <html><head/><body><p>Escriba el número de puerto que WSJT-X debe usar para las transmisiones UDP del log ADIF guardado. Para N1MM Logger + este valor debe ser 2333. Si es cero, no se transmitirán actualizaciones.</p></body></html> @@ -7531,65 +7551,65 @@ Clic derecho para insertar y eliminar opciones. Versión de la aplicación - + Another instance may be running Otra instancia puede estar ejecutándose - + try to remove stale lock file? ¿intentas eliminar el archivo de bloqueo obsoleto? ¿intentar eliminar el archivo de bloqueo? - + Failed to create a temporary directory Error al crear un directorio temporal - - + + Path: "%1" Ruta: "%1" - + Failed to create a usable temporary directory Error al crear un directorio temporal utilizable Error al crear un directorio temporal - + Another application may be locking the directory Otra aplicación puede estar bloqueando el directorio - + Failed to create data directory Error al crear el directorio de datos - + path: "%1" ruta: "%1" - + Shared memory error Error de memoria compartida - + Unable to create shared memory segment No se puede crear un segmento de memoria compartida - + Sub-process error Error en subproceso - + Failed to close orphaned jt9 process No se pudo cerrar los procesos huerfanos de JT9 diff --git a/translations/wsjtx_it.ts b/translations/wsjtx_it.ts index 9ab2dab13..e9588d3eb 100644 --- a/translations/wsjtx_it.ts +++ b/translations/wsjtx_it.ts @@ -369,75 +369,75 @@ Configuration::impl - - - + + + &Delete &Elimina - - + + &Insert ... &Inserisci ... - + Failed to create save directory Impossibile creare la directory di salvataggio - + path: "%1% Percorso: "%1" - + Failed to create samples directory Impossibile creare la directory dei campioni - + path: "%1" Percorso: "%1" - + &Load ... &Carica ... - + &Save as ... &Salva come ... - + &Merge ... &Unisci ... - + &Reset &Ripristina - + Serial Port: Porta Seriale: - + Serial port used for CAT control Porta Seriale usata per il controllo CAT - + Network Server: Server di rete: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -452,12 +452,12 @@ Formati: [IPv6-address]: porta - + USB Device: Dispositivo USB: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -468,8 +468,8 @@ Formato: [VID [: PID [: VENDOR [: PRODOTTI]]]] - - + + Invalid audio input device Dispositivo di ingresso audio non valido @@ -478,150 +478,156 @@ Formato: Dispositivo di uscita audio non valido - + Invalid audio output device Dispositivo di uscita audio non valido - + Invalid PTT method Metodo PTT non valido - + Invalid PTT port Porta PTT non valida - - + + Invalid Contest Exchange Scambio Contest non valido - + You must input a valid ARRL Field Day exchange È necessario inserire uno scambioField Day ARRL valido - + You must input a valid ARRL RTTY Roundup exchange È necessario inserire uno scambio Roundup RTTY ARRL valido - + Reset Decode Highlighting Ripristina l'evidenziazione della decodifica - + Reset all decode highlighting and priorities to default values Ripristina tutti i valori di evidenziazione e priorità della decodifica sui valori predefiniti - + WSJT-X Decoded Text Font Chooser Selezionatore font testo decodificato WSJT-X - + Load Working Frequencies Carica frequenze di lavoro - - - + + + Frequency files (*.qrg);;All files (*.*) File di frequenza (*.qrg);;Tutti i file (*.*) - + Replace Working Frequencies Sostituisci le frequenze di lavoro - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? Sei sicuro di voler scartare le tue attuali frequenze di lavoro e sostituirle con quelle caricate? - + Merge Working Frequencies Unisci le frequenze di lavoro - - - + + + Not a valid frequencies file Non è un file di frequenze valido - + Incorrect file magic Magic file errato - + Version is too new La versione è troppo nuova - + Contents corrupt Contenuto corrotto - + Save Working Frequencies Salva frequenze di lavoro - + Only Save Selected Working Frequencies Salva solo le frequenze di lavoro selezionate - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. Sei sicuro di voler salvare solo le frequenze di lavoro che sono attualmente selezionate? Fai clic su No per salvare tutto. - + Reset Working Frequencies Ripristina frequenze di lavoro - + Are you sure you want to discard your current working frequencies and replace them with default ones? Sei sicuro di voler scartare le tue attuali frequenze di lavoro e sostituirle con quelle predefinite? - + Save Directory Salva il direttorio - + AzEl Directory AzEl Direttorio - + Rig control error Errore di controllo rig - + Failed to open connection to rig Impossibile aprire la connessione al rig - + Rig failure Rig fallito + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1448,22 +1454,22 @@ Errore: %2 - %3 FrequencyDialog - + Add Frequency Aggiungi frequenza - + IARU &Region: &Regione IARU: - + &Mode: &Modo: - + &Frequency (MHz): &Frequenza (MHz): @@ -1585,180 +1591,180 @@ Errore: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Errore di inizializzazione di Hamlib - + Hamlib settings file error: %1 at character offset %2 Errore del file delle impostazioni di Hamlib:%1 all'offset del carattere %2 - + Hamlib settings file error: top level must be a JSON object Errore del file delle impostazioni di Hamlib: il livello principale deve essere un oggetto JSON - + Hamlib settings file error: config must be a JSON object Errore del file delle impostazioni di Hamlib: config deve essere un oggetto JSON - + Unsupported CAT type Tipo CAT non supportato - + Hamlib error: %1 while %2 Errore Hamlib: %1 mentre %2 - + opening connection to rig apertura connessione al rig - + getting current frequency ottenere la frequenza corrente - + getting current mode ottenere la modalità corrente - - + + exchanging VFOs scambio di VFO - - + + getting other VFO frequency ottenere altra frequenza VFO - + getting other VFO mode ottenere altra modalità VFO - - + + setting current VFO impostazione del VFO corrente - + getting frequency ottenere la frequenza - + getting mode ottenere il modo - - - + + + getting current VFO ottenere il VFO corrente - - - - + + + + getting current VFO frequency ottenere la frequenza del VFO corrente - - - - - - + + + + + + setting frequency impostazione della frequenza - - - - + + + + getting current VFO mode ottenere il modo del VFO corrente - - - - - + + + + + setting current VFO mode impostare il modo del VFO corrente - - + + setting/unsetting split mode impostazione / disinserimento della modalità split - - + + setting split mode - + setting split TX frequency and mode impostazione della frequenza e della modalità TX divise - + setting split TX frequency impostazione della frequenza Split TX - + getting split TX VFO mode ottenere la modalità split VFO TX - + setting split TX VFO mode impostazione della modalità VFO split TX - + getting PTT state ottenere lo stato PTT - + setting PTT on attivare PTT - + setting PTT off disattivare PTT - + setting a configuration item impostazione di un elemento di configurazione - + getting a configuration item ottenere un elemento di configurazione @@ -2094,196 +2100,196 @@ Errore (%2):%3 WSJT-X di K1JT - - - - - - - - + + + + + + + + Band Activity Attività di Banda - - + + UTC dB DT Freq Dr UTC dB DT Freq Dr - - - - - - - + + + + + + + Rx Frequency Frequenza Rx - + CQ only Solo CQ - + Enter this QSO in log Immettere questo QSO nel log - + Log &QSO Log &QSO - + Stop monitoring Interrompere il monitoraggio - + &Stop &Stop - + Toggle monitoring On/Off Attiva / disattiva il monitoraggio - + &Monitor &Monitor - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>Cancella la finestra a destra. Fare doppio clic per cancellare entrambe le finestre.</p></body></html> - + Erase right window. Double-click to erase both windows. Cancella la finestra a destra. Fare doppio clic per cancellare entrambe le finestre. - + &Erase &Cancella - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body><p>Cancella la media dei messaggi accumulati.</p></body></html> - + Clear the accumulating message average. Cancella la media dei messaggi accumulati. - + Clear Avg Cancella media - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body><p>Decodifica il periodo Rx più recente alla frequenza QSO</p></body></html> - + Decode most recent Rx period at QSO Frequency Decodifica il periodo Rx più recente alla frequenza QSO - + &Decode &Decodifica - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body> <p> Attiva / Disattiva Auto-Tx </p> </body> </html> - + Toggle Auto-Tx On/Off Attiva / Disattiva Auto-Tx - + E&nable Tx &Abilita Tx - + Stop transmitting immediately Interrompere immediatamente la trasmissione - + &Halt Tx &Arresta Tx - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>Attiva / disattiva un tono Tx puro</p></body></html> - + Toggle a pure Tx tone On/Off Attiva / disattiva un tono Tx puro - + &Tune &Accorda - + Menus Menù - + Percentage of minute sequences devoted to transmitting. Percentuale di sequenze minuti dedicate alla trasmissione. - + Prefer Type 1 messages Preferisci i messaggi di tipo 1 - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>Trasmetti durante la sequenza successiva.</p></body></html> - + USB dial frequency Frequenza di chiamata USB - + 14.078 000 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body><p>30dB consigliato quando è presente solo rumore<br/>Verde quando buono<br/>Rosso quando può verificarsi distorsione<br/>Giallo quando troppo basso</p></body></html> - + Rx Signal Segnale Rx - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2294,344 +2300,344 @@ Rosso quando può verificarsi distorsione Giallo quando troppo basso - + DX Call Nominativo DX - + DX Grid Griglia DX - + Callsign of station to be worked Nominativo statione da collegare - + Search for callsign in database Ricerca nominativo nel database - + &Lookup &Ricerca - + Locator of station to be worked Localizzatore della stazione da lavorare - + Az: 251 16553 km Az: 251 16553 km - + Add callsign and locator to database Aggiungi nominativo e localizzatore al database - + Add Aggiungi - + Pwr Potenza - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body><p>Se arancione o rosso si è verificato un errore nel controllo rig, fare clic per ripristinare e leggere la frequenza di sintonia. S implica la modalità split.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. Se arancione o rosso si è verificato un errore nel controllo rig, fare clic per ripristinare e leggere la frequenza di sintonia. S implica la modalità split. - + ? ? - + Adjust Tx audio level Regola il livello audio Tx - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body><p>Seleziona la banda operativa o inserisci la frequenza in MHz o inserisci l'incremento di kHz seguito da k.</p></body></html> - + Frequency entry Immetti la frequenza - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. Seleziona la banda operativa o inserisci la frequenza in MHz o inserisci l'incremento di kHz seguito da k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> <html><head/><body><p align="center"> 2015 Giu 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body><p>Spuntare la casella per mantenere fissa la frequenza Tx quando si fa doppio clic sul testo decodificato.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. Spuntare la casella per mantenere fissa la frequenza Tx quando si fa doppio clic sul testo decodificato. - + Hold Tx Freq Mantenere premuto Tx Freq - + Audio Rx frequency Frequenza audio Rx - - - - - + + + + + Hz Hz - - + + Rx Rx - - + + Set Tx frequency to Rx Frequency Impostare la frequenza Tx su Frequenza Rx - + - + Frequency tolerance (Hz) Tolleranza di frequenza (Hz) - - + + F Tol F Tol - - + + Set Rx frequency to Tx Frequency Impostare la frequenza Rx su Frequenza Tx - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body><p>Sincronizzazione della soglia. I numeri più bassi accettano segnali di sincronizzazione più deboli.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. Sincronizzazione della soglia. I numeri più bassi accettano segnali di sincronizzazione più deboli. - + Sync Sinc - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>Selezionare per utilizzare i messaggi di formato breve.</p></body></html> - + Check to use short-format messages. Selezionare per utilizzare i messaggi di formato breve. - + Sh Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>Selezionare per abilitare le modalità rapide JT9</p></body></html> - + Check to enable JT9 fast modes Selezionare per abilitare le modalità rapide JT9 - - + + Fast Veloce - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body><p>Selezionare per abilitare il sequenziamento automatico dei messaggi Tx in base ai messaggi ricevuti.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. Selezionare per abilitare il sequenziamento automatico dei messaggi Tx in base ai messaggi ricevuti. - + Auto Seq Auto Seq - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body><p>Selezionare per chiamare il primo risponditore decodificato al mio CQ.</p></body></html> - + Check to call the first decoded responder to my CQ. Selezionare per chiamare il primo risponditore decodificato al mio CQ. - + Call 1st Chiama il 1º - + Check to generate "@1250 (SEND MSGS)" in Tx6. Selezionare per generare "@1250 (INVIO MSGS)" in Tx6. - + Tx6 Tx6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body><p>Selezionare su Tx in minuti o sequenze di numero pari, iniziando da 0; deselezionare le sequenze dispari.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. Selezionare su Tx in minuti o sequenze di numero pari, iniziando da 0; deselezionare le sequenze dispari. - + Tx even/1st Tx pari/1º - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body> <p> Frequenza di chiamata CQ in kHz sopra l'attuale MHz </p> </body> </html> - + Frequency to call CQ on in kHz above the current MHz Frequenza per chiamare CQ in kHz sopra l'attuale MHz - + Tx CQ Tx CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body><p>Spunta questo per chiamare CQ sulla frequenza &quot;Tx CQ&quot;.L' Rx sarà sulla frequenza corrente e il messaggio CQ includerà la frequenza Rx corrente in modo che i chiamanti sappiano su quale frequenza rispondere. Non disponibile per i possessori di nominativi non standard.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. Spunta questo per chiamare CQ sulla frequenza "Tx CQ". Rx sarà sulla frequenza corrente e il messaggio CQ includerà la frequenza Rx corrente in modo che i chiamanti sappiano su quale frequenza rispondere. Non disponibile per i possessori di nominativi non standard. - + Rx All Freqs Rx Tutte le freq - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body> <p> La modalità secondaria determina la spaziatura dei toni; A è il più stretto. </p> </body> </html> - + Submode determines tone spacing; A is narrowest. La modalità secondaria determina la spaziatura dei toni; A è il più stretto. - + Submode Modalità Secondaria - - + + Fox Fox - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>Spuntare per monitorare i messaggi Sh.</p></body></html> - + Check to monitor Sh messages. Spuntare per monitorare i messaggi Sh. - + SWL SWL - + Best S+P Migliore S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body><p>Seleziona questa opzione per avviare la registrazione dei dati di calibrazione.<br/>Mentre la misurazione della correzione della calibrazione è disabilitata.<br/>Se non selezionato puoi visualizzare i risultati della calibrazione.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2640,206 +2646,216 @@ Durante la misurazione, la correzione della calibrazione è disabilitata. Se non selezionato, è possibile visualizzare i risultati della calibrazione. - + Measure Misura - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body><p>Rapporto segnale: rapporto segnale-rumore nella larghezza di banda di riferimento di 2500 Hz (dB).</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). Rapporto segnale: rapporto segnale-rumore nella larghezza di banda di riferimento di 2500 Hz (dB). - + Report Rapporto - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>TX/RX o Lunghezza della sequenza di calibrazione della frequenza</p></body></html> - + Tx/Rx or Frequency calibration sequence length TX/RX o Lunghezza della sequenza di calibrazione della frequenza - - + + s s - - + + T/R T/R - + Toggle Tx mode Attiva / disattiva la modalità Tx - + Tx JT9 @ Tx JT9 @ - + Audio Tx frequency Frequenza Tx audio - - + + Tx Tx - + Tx# Tx# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body><p>Fare doppio clic su un altro chiamante per mettere in coda quella chiamata per il QSO successivo.</p></body></html> - + + F High + + + + + F Low + + + + Double-click on another caller to queue that call for your next QSO. Fare doppio clic su un altro chiamante per mettere in coda quella chiamata per il QSO successivo. - + Next Call Prossima chiamata - + 1 1 - - - + + + Send this message in next Tx interval Invia questo messaggio nel prossimo intervallo Tx - + Ctrl+2 Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>Invia questo messaggio nel prossimo intervallo Tx </p><p>Fare doppio clic per alternare l'uso del messaggio Tx1 per avviare un QSO con una stazione (non consentito per i detentori di chiamate composte di tipo 1)</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Invia questo messaggio nel prossimo intervallo Tx Fare doppio clic per attivare / disattivare l'uso del messaggio Tx1 per avviare un QSO con una stazione (non consentito per i detentori di chiamate composte di tipo 1) - + Ctrl+1 Ctrl+1 - - - - + + + + Switch to this Tx message NOW Passa a questo messaggio Tx ADESSO - + Tx &2 Tx &2 - + Alt+2 Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>Passa a questo messaggio Tx ORA</p><p>Fai doppio clic per attivare o disattivare l'uso del messaggio Tx1 per avviare un QSO con una stazione (non consentito per i detentori di chiamate composte di tipo 1)</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) Passa a questo messaggio Tx ADESSO Fare doppio clic per attivare / disattivare l'uso del messaggio Tx1 per avviare un QSO con una stazione (non consentito per i detentori di chiamate composte di tipo 1) - + Tx &1 Tx &1 - + Alt+1 Alt+1 - + Ctrl+6 Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Invia questo messaggio nel prossimo intervallo Tx</p><p>Fare doppio clic per ripristinare il messaggio 73 standard</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message Invia questo messaggio nel prossimo intervallo Tx Fare doppio clic per ripristinare il messaggio 73 standard - + Ctrl+5 Ctrl+5 - + Ctrl+3 Ctrl+3 - + Tx &3 Tx &3 - + Alt+3 Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>Invia questo messaggio nel prossimo intervallo Tx</p><p>Fare doppio clic per alternare tra i messaggi RRR e RR73 in Tx4 (non consentito per i possessori di chiamate composte di tipo 2)</p><p>I messaggi RR73 devono essere utilizzati solo quando si è ragionevolmente sicuri che non saranno necessarie ripetizioni dei messaggi</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2848,17 +2864,17 @@ Fare doppio clic per alternare tra i messaggi RRR e RR73 in Tx4 (non consentito I messaggi RR73 devono essere utilizzati solo quando si è ragionevolmente sicuri che non saranno necessarie ripetizioni dei messaggi - + Ctrl+4 Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>Passa a questo messaggio Tx ORA</p><p>Fai doppio clic per alternare tra i messaggi RRR e RR73 in Tx4 (non consentito per i possessori di chiamate composte di tipo2)</p><p>I messaggi RR73 devono essere utilizzati solo quando sei ragionevolmente sicuro che non sarà richiesta alcuna ripetizione del messaggio</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2867,64 +2883,64 @@ Fare doppio clic per alternare tra i messaggi RRR e RR73 in Tx4 (non consentito I messaggi RR73 devono essere utilizzati solo quando si è ragionevolmente sicuri che non saranno necessarie ripetizioni dei messaggi - + Tx &4 Tx &4 - + Alt+4 Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>Passa a questo messaggio Tx ADESSO</p><p>Fai doppio clic per ripristinare il messaggio 73 standard</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message Passa a questo messaggio Tx ADESSO Fare doppio clic per ripristinare il messaggio 73 standard - + Tx &5 Tx &5 - + Alt+5 Alt+5 - + Now Now - + Generate standard messages for minimal QSO Genera messaggi standard per un QSO minimo - + Generate Std Msgs Genera Std Msgs - + Tx &6 Tx &6 - + Alt+6 Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2935,26 +2951,36 @@ Premere INVIO per aggiungere il testo corrente al predefinito elenco. L'elenco può essere gestito in Impostazioni (F2). - + Queue up the next Tx message Accoda il prossimo messaggio Tx - + Next Prossimo - + 2 2 - + FST4W FST4:Nuova famiglia di modalità digitali. FST4W:Messaggi simili al WSPR FST4W + + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + Calling CQ Chiamando CQ @@ -2964,8 +2990,8 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Genera un messaggio CQ - - + + CQ CQ @@ -2994,7 +3020,7 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Genera messaggio di risposta al CQ - + Grid Griglia @@ -3035,138 +3061,138 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). 3 - + Max dB Max dB - + CQ AF CQ AF - + CQ AN CQ AN - + CQ AS CQ AS - + CQ EU CQ EU - + CQ NA CQ NA - + CQ OC CQ OC - + CQ SA CQ SA - + CQ 0 CQ 0 - + CQ 1 CQ 1 - + CQ 2 CQ 2 - + CQ 3 CQ 3 - + CQ 4 CQ 4 - + CQ 5 CQ 5 - + CQ 6 CQ 6 - + CQ 7 CQ 7 - + CQ 8 CQ 8 - + CQ 9 CQ 9 - + Reset Ripristina - + N List N List - + N Slots N Slots - - - - - - - + + + + + + + Random Casuale - + Call Nominativo - + S/N (dB) S/N (dB) - + Distance Distanza - + More CQs Più CQs @@ -3175,164 +3201,164 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Percentuale di sequenze di 2 minuti dedicate alla trasmissione. - - + + % % - + Tx Pct Tx Pct - + Band Hopping Band Hopping - + Choose bands and times of day for band-hopping. Scegli le fasce e gli orari del giorno per il band-hopping. - + Schedule ... Programma ... - + 1/2 1/2 1/2 - + 2/2 2/2 2/2 - + 1/3 1/3 1/3 - + 2/3 2/3 2/3 - + 3/3 3/3 3/3 - + 1/4 1/4 1/4 - + 2/4 2/4 - + 3/4 3/4 - + 4/4 4/4 - + 1/5 1/5 - + 2/5 2/5 - + 3/5 3/5 - + 4/5 4/5 - + 5/5 5/5 - + 1/6 1/6 - + 2/6 2/6 - + 3/6 3/6 - + 4/6 4/6 - + 5/6 5/6 - + 6/6 6/6 - + Upload decoded messages to WSPRnet.org. Carica messaggi decodificati su WSPRnet.org. - + Upload spots Carica spot - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>I localizzatori a 6 cifre causano l'invio di 2 messaggi diversi, il secondo contiene il localizzatore completo ma solo un nominativo con hash, altre stazioni devono aver decodificato il primo una volta prima di poter decodificare la chiamata nel secondo. Selezionare questa opzione per inviare localizzatori a 4 cifre solo se si eviterà il protocollo a due messaggi.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. I localizzatori a 6 cifre causano l'invio di 2 messaggi diversi, il secondo contiene il localizzatore completo ma solo un nominativo con hash, altre stazioni devono aver decodificato il primo una volta prima di poter decodificare la chiamata nel secondo. Selezionare questa opzione per inviare localizzatori a 4 cifre solo se si eviterà il protocollo a due messaggi. - + Quick-Start Guide to FST4 and FST4W Guida Rapida al FST4 e FST4W - + FST4 FST4:Nuova famiglia di modalità digitali. FST4 @@ -3346,7 +3372,7 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Preferisci i messaggi di tipo 1 - + No own call decodes Nessuna decodifica del proprio nominativo @@ -3355,62 +3381,62 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Trasmettere durante la sequenza di 2 minuti successiva. - + Tx Next Tx Successiva - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. Imposta la potenza Tx in dBm (dB sopra 1 mW) come parte del tuo messaggio WSPR. - + NB NB - + File File - + View Vista - + Decode Decodificare - + Save Salva - + Help Aiuto - + Mode Modo - + Configurations Configurazioni - + Tools Strumenti - + Exit Uscita @@ -3423,87 +3449,87 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). F2 - + About WSJT-X Informazioni su WSJT-X - + Waterfall Display a cascata - + Open Apri - + Ctrl+O Ctrl+O - + Open next in directory Apri successivo nella directory - + Decode remaining files in directory Decodifica i file rimanenti nella directory - + Shift+F6 Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir Elimina tutti i file * .wav && * .c2 nel direttorio - + None Nessuno - + Save all Salva tutto - + Online User Guide Guida per l'utente online - + Keyboard shortcuts Scorciatoie da tastiera - + Special mouse commands Comandi speciali mouse - + JT9 JT9 - + Save decoded Salva decodificato - + Normal Normale - + Deep Profondo @@ -3512,12 +3538,12 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Monitor OFF all'avvio - + Erase ALL.TXT Cancella ALL.TXT - + Erase wsjtx_log.adi Cancella wsjtx_log.adi @@ -3550,7 +3576,7 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Fare doppio clic sui set di chiamate Abilita Tx - + F7 F7 @@ -3559,7 +3585,7 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Tx disabilitato dopo l'invio 73 - + Runaway Tx watchdog Watchdog Tx sfuggito @@ -3572,12 +3598,12 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Tx freq bloccato su Rx freq - + JT65 JT65 - + JT9+JT65 JT9+JT65 @@ -3594,147 +3620,147 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Mostra entità DXCC e stato B4 lavorato - + Astronomical data Dati Astronomici - + List of Type 1 prefixes and suffixes Elenco di prefissi e suffissi di tipo 1 - + Settings... Impostazioni... - + Local User Guide Guida per l'utente locale - + Open log directory Apri il direttorio del Log - + JT4 JT4 - + Message averaging Media dei messaggi - + Enable averaging Abilita Media - + Enable deep search Abilita ricerca profonda - + WSPR WSPR - + Echo Graph Grafico Eco - + F8 F8 - + Echo Eco - + EME Echo mode Modo Eco EME - + ISCAT ISCAT - + Fast Graph Grafico Veloce - + F9 F9 - + &Download Samples ... &Scarica Campioni ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>Scarica file audio di esempio che dimostrano le varie modalità.</p></body></html> - + MSK144 MSK144 - + QRA64 QRA64 - + Release Notes Note di rilascio - + Enable AP for DX Call Abilita AP per DX Call - + FreqCal FreqCal - + Measure reference spectrum Misurare lo spettro di riferimento - + Measure phase response Misura la risposta di fase - + Erase reference spectrum Cancella spettro di riferimento - + Execute frequency calibration cycle Eseguire il ciclo di calibrazione della frequenza - + Equalization tools ... Strumenti di equalizzazione ... @@ -3747,48 +3773,48 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Modo Sperimentale LF/MF - + FT8 FT8 - - + + Enable AP Abilita AP - + Solve for calibration parameters Risolvi per i parametri di calibrazione - + Copyright notice Avviso sul copyright - + Shift+F1 Shift+F1 - + Fox log Fox log - + FT8 DXpedition Mode User Guide Manuale Utente modo FT8 DXpedition - + Reset Cabrillo log ... Ripristina Cabrillo log ... - + Color highlighting scheme Schema di evidenziazione del colore @@ -3797,7 +3823,7 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Log del Contest - + Export Cabrillo log ... Esporta Log Cabrillo ... @@ -3806,49 +3832,49 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Guida rapida per WSJT-X 2.0 - + Contest log Log del Contest - + Erase WSPR hashtable Cancella hashtable WSPR - + FT4 FT4 - + Rig Control Error Errore di controllo rig - - - + + + Receiving Ricevente - + Do you want to reconfigure the radio interface? Vuoi riconfigurare l'interfaccia radio? - + %1 (%2 sec) audio frames dropped %1 (%2 sec) frames audio perse - + Audio Source Sorgente Audio - + Reduce system load Riduci carico di sistema @@ -3857,194 +3883,194 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). Eccessivi campioni persi - %1 (%2 sec) frames audio ignorate - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Error Scanning ADIF Log Errore durante la scansione del registro ADIF - + Scanned ADIF log, %1 worked before records created Log ADIF scansionato,%1 ha funzionato prima della creazione dei record - + Error Loading LotW Users Data Errore durante il caricamento dei dati degli utenti di LotW - + Error Writing WAV File Errore durante la scrittura del file WAV - + Enumerating audio devices - + Configurations... Configurazioni... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message Messaggio - + Error Killing jt9.exe Process Errore durante l'uccisione del processo jt9.exe - + KillByName return code: %1 Codice di ritorno KillByName:%1 - + Error removing "%1" Errore durante la rimozione di "%1" - + Click OK to retry Fai clic su OK per riprovare - - + + Improper mode Modalità impropria - - + + File Open Error Errore apertura file - - - - - + + + + + Cannot open "%1" for append: %2 Impossibile aprire "%1" per aggiungere:%2 - + Error saving c2 file Errore salvataggio file c2 - + Error in Sound Input Errore nell'ingresso audio - + Error in Sound Output Errore nell'uscita audio - - - + + + Single-Period Decodes Decodifiche a periodo singolo - - - + + + Average Decodes Media Decodifiche - + Change Operator Cambio Operatore - + New operator: Nuovo operatore: - + Status File Error Errore del file di stato - - + + Cannot open "%1" for writing: %2 Impossibile aprire "%1" per la scrittura:%2 - + Subprocess Error Errore sottoprocesso - + Subprocess failed with exit code %1 Il sottoprocesso non è riuscito con il codice di uscita%1 - + Running: %1 %2 In esecuzione: %1 %2 - + Subprocess error Errore sottoprocesso - + Reference spectrum saved Spettro di riferimento salvato - + Invalid data in fmt.all at line %1 Dati non validi in fmt.all alla riga%1 - + Good Calibration Solution Buona soluzione di calibrazione - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -4057,17 +4083,17 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). %9%L10 Hz</pre> - + Delete Calibration Measurements Elimina misure di calibrazione - + The "fmt.all" file will be renamed as "fmt.bak" Il file "fmt.all" verrà rinominato come "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -4076,27 +4102,27 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). "Gli algoritmi, il codice sorgente, l'aspetto di WSJT-X e dei relativi programmi e le specifiche del protocollo per le modalità FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 sono Copyright (C) 2001-2020 di uno o più dei seguenti autori: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q e altri membri del WSJT Development Group. " - + No data read from disk. Wrong file format? Nessun dato letto dal disco. Formato file errato? - + Confirm Delete Conferma Eliminazione - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? Sei sicuro di voler eliminare tutti i file * .wav e * .c2 in "%1"? - + Keyboard Shortcuts Scorciatoie da tastiera - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4284,12 +4310,12 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). </table> - + Special Mouse Commands Comandi speciali mouse - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4356,42 +4382,42 @@ elenco. L'elenco può essere gestito in Impostazioni (F2). </table> - + No more files to open. Niente più file da aprire. - + Spotting to PSK Reporter unavailable Spotting su PSK Reporter non disponibile - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. Scegli un'altra frequenza Tx. WSJT-X non trasmetterà consapevolmente un'altra modalità nella sottobanda WSPR a 30 m. - + WSPR Guard Band Banda di guardia WSPR - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. Scegli un'altra frequenza di composizione. WSJT-X non funzionerà in modalità Fox nelle sottobande FT8 standard. - + Fox Mode warning Avviso modalità Fox - + Last Tx: %1 Ultimo Tx:%1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4402,121 +4428,121 @@ Per fare ciò, selezionare "Attività operativa speciale" e "Contest VHF EU" sulle impostazioni | Scheda Avanzate. - + Should you switch to ARRL Field Day mode? Dovresti passare alla modalità Field Day di ARRL? - + Should you switch to RTTY contest mode? Dovresti passare alla modalità contest RTTY? - - - - + + + + Add to CALL3.TXT Aggiungi a CALL3.TXT - + Please enter a valid grid locator Inserisci un localizzatore di griglia valido - + Cannot open "%1" for read/write: %2 Impossibile aprire "%1" per lettura / scrittura:%2 - + %1 is already in CALL3.TXT, do you wish to replace it? %1 è già in CALL3.TXT, desideri sostituirlo? - + Warning: DX Call field is empty. Avviso: il campo Chiamata DX è vuoto. - + Log file error Errore nel file di registro - + Cannot open "%1" Impossibile aprire "%1" - + Error sending log to N1MM Errore durante l'invio del Log a N1MM - + Write returned "%1" Scrivi ha restituito "%1" - + Stations calling DXpedition %1 Stazioni che chiamano la DXpedition %1 - + Hound (Hound=Cane da caccia) Hound - + Tx Messages Messaggi Tx - - - + + + Confirm Erase Conferma Cancella - + Are you sure you want to erase file ALL.TXT? Sei sicuro di voler cancellare il file ALL.TXT? - - + + Confirm Reset Conferma Ripristina - + Are you sure you want to erase your contest log? Sei sicuro di voler cancellare il tuo Log del contest? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. In questo modo verranno rimossi tutti i record QSO per il contest corrente. Saranno conservati nel file di registro ADIF ma non saranno disponibili per l'esportazione nel registro Cabrillo. - + Cabrillo Log saved Log Cabrillo salvato - + Are you sure you want to erase file wsjtx_log.adi? Sei sicuro di voler cancellare il file wsjtx_log.adi? - + Are you sure you want to erase the WSPR hashtable? Sei sicuro di voler cancellare la tabella hash WSPR? @@ -4525,60 +4551,60 @@ is already in CALL3.TXT, do you wish to replace it? VHF presenta un avviso - + Tune digital gain Ottimizza il guadagno digitale - + Transmit digital gain Trasmetti Guadagno digitale - + Prefixes Prefissi - + Network Error Errore di Rete - + Error: %1 UDP server %2:%3 Errore:%1 Server UDP%2:%3 - + File Error Errore File - + Phase Training Disabled Fase di Allenamento Disabilitato - + Phase Training Enabled Fase di allenamento abilitato - + WD:%1m WD:%1m - - + + Log File Error Errore file di Log - + Are you sure you want to clear the QSO queues? Sei sicuro di voler cancellare le code QSO? @@ -4925,22 +4951,21 @@ Errore (%2):%3 SoundInput - + An error opening the audio input device has occurred. Si è verificato un errore durante l'apertura del dispositivo di input audio. - + An error occurred during read from the audio input device. Si è verificato un errore durante la lettura dal dispositivo di ingresso audio. - Audio data not being fed to the audio input device fast enough. - I dati audio non vengono inviati al dispositivo di input audio abbastanza velocemente. + I dati audio non vengono inviati al dispositivo di input audio abbastanza velocemente. - + Non-recoverable error, audio input device not usable at this time. Errore non recuperabile, dispositivo di input audio non utilizzabile in questo momento. @@ -4955,37 +4980,37 @@ Errore (%2):%3 Il formato audio di input richiesto non è supportato sul dispositivo. - + Failed to initialize audio sink device Impossibile inizializzare il dispositivo sink audio - + Idle Inattivo - + Receiving Ricevente - + Suspended Sospeso - + Interrupted Interrotto - + Error Errore - + Stopped Fermato @@ -4993,67 +5018,67 @@ Errore (%2):%3 SoundOutput - + An error opening the audio output device has occurred. Si è verificato un errore durante l'apertura del dispositivo di uscita audio. - + An error occurred during write to the audio output device. Si è verificato un errore durante la scrittura sul dispositivo di uscita audio. - + Audio data not being fed to the audio output device fast enough. I dati audio non vengono inviati al dispositivo di uscita audio abbastanza velocemente. - + Non-recoverable error, audio output device not usable at this time. Errore non recuperabile, dispositivo di uscita audio non utilizzabile in questo momento. - + Requested output audio format is not valid. Il formato audio di output richiesto non è valido. - + Requested output audio format is not supported on device. Il formato audio di output richiesto non è supportato sul dispositivo. - + No audio output device configured. Nessun dispositivo di uscita audio configurato. - + Idle Inattivo - + Sending Invio - + Suspended Sospeso - + Interrupted Interrotto - + Error Errore - + Stopped Fermato @@ -5061,22 +5086,22 @@ Errore (%2):%3 StationDialog - + Add Station Aggoingi Stazione - + &Band: &Banda: - + &Offset (MHz): &Offset (MHz): - + &Antenna: &Antenna: @@ -6064,7 +6089,7 @@ l'interfaccia radio si comporta come previsto. Scheda audio - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -6082,46 +6107,46 @@ periodi di trasmissione. Giorni dall'ultimo aggiornamento - + Select the audio CODEC to use for receiving. Seleziona l'audio CODEC da utilizzare per la ricezione. - + &Input: &Ingresso: - + Select the channel to use for receiving. Seleziona il canale da utilizzare per la ricezione. - - + + Mono Mono - - + + Left Sinistro - - + + Right Destro - - + + Both Entrambi - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -6137,7 +6162,7 @@ entrambi qui. Abilita le funzioni VHF e sottomodalità - + Ou&tput: Usci&ta: @@ -6396,67 +6421,67 @@ per valutare la propagazione e le prestazioni del sistema. <html><head/><body><p>Immettere il numero di porta del servizio del server UDP a cui WSJT-X deve inviare gli aggiornamenti. Se questo è zero, non verranno trasmessi aggiornamenti.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p>Con questo abilitato WSJT-X accetterà alcune richieste di ritorno da un server UDP che riceve messaggi di decodifica.</p></body></html> - + Accept UDP requests Accetta richieste UDP - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p>Indica l'accettazione di una richiesta UDP in arrivo. L'effetto di questa opzione varia a seconda del sistema operativo e del gestore delle finestre, il suo intento è di notificare l'accettazione di una richiesta UDP in arrivo anche se questa applicazione è ridotta a icona o nascosta.</p></body></html> - + Notify on accepted UDP request Notifica su richiesta UDP accettata - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p>Ripristina la finestra da minimizzata se viene accettata una richiesta UDP.</p></body></html> - + Accepted UDP request restores window Finestra di ripristino richieste UDP accettate - + Secondary UDP Server (deprecated) Server UDP Secondario (obsoleto) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p>Se selezionato, WSJT-X trasmetterà un contatto registrato in formato ADIF al nome host e alla porta configurati.</p></body></html> - + Enable logged contact ADIF broadcast Abilita trasmissione ADIF del contatto registrato - + Server name or IP address: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>Nome host facoltativo del programma Logger + N1MM per ricevere trasmissioni UDP ADIF. Di solito si tratta di "localhost" o indirizzo IP 127.0.0.1</p><p>Formati:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Indirizzo IPv4</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Indirizzo IPv6</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Indirizzo di gruppo multicast IPv4</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Indirizzo di gruppo multicast IPv6</li></ul><p>La cancellazione di questo campo disabiliterà la trasmissione di informazioni ADIF tramite UDP.</p></body></html> - + Server port number: Numero porta Server: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>Immettere il numero di porta che WSJT-X deve utilizzare per le trasmissioni UDP delle informazioni del registro ADIF. Per N1MM Logger +, questo valore dovrebbe essere 2333. Se questo è zero, non verrà trasmesso alcun aggiornamento.</p></body></html> @@ -6912,63 +6937,63 @@ Fare clic con il tasto destro per inserire ed eliminare le opzioni.Errore fatale inatteso - + Another instance may be running Un'altra istanza potrebbe essere in esecuzione - + try to remove stale lock file? Provo a rimuovere il file di blocco non aggiornato? - + Failed to create a temporary directory Impossibile creare una directory temporanea - - + + Path: "%1" Percorso: "%1" - + Failed to create a usable temporary directory Impossibile creare una directory temporanea utilizzabile - + Another application may be locking the directory Un'altra applicazione potrebbe bloccare la directory - + Failed to create data directory Impossibile creare la directory dei dati - + path: "%1" percorso: "%1" - + Shared memory error Errore di memoria condivisa - + Unable to create shared memory segment Impossibile creare il segmento di memoria condivisa - + Sub-process error Errore sottoprocesso - + Failed to close orphaned jt9 process Impossibile chiudere il processo jt9 orfano diff --git a/translations/wsjtx_ja.ts b/translations/wsjtx_ja.ts index c4cfae0bc..0cf5f52bb 100644 --- a/translations/wsjtx_ja.ts +++ b/translations/wsjtx_ja.ts @@ -368,75 +368,75 @@ Configuration::impl - - - + + + &Delete 削除(&D) - - + + &Insert ... 挿入(&I)... - + Failed to create save directory 保存のためのフォルダを作成できません - + path: "%1% パス: "%1% - + Failed to create samples directory サンプルフォルダを作成できません - + path: "%1" パス: "%1" - + &Load ... 読み込み(&L)... - + &Save as ... 名前を付けて保存(&S)... - + &Merge ... 結合(&M)... - + &Reset リセット(&R) - + Serial Port: シリアルポート: - + Serial port used for CAT control CAT制御用シリアルポート - + Network Server: ネットワークサーバ: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -451,12 +451,12 @@ Formats: [IPv6-アドレス]:ポート番号 - + USB Device: USBデバイス: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -467,8 +467,8 @@ Format: [VID[:PID[:VENDOR[:PRODUCT]]]] - - + + Invalid audio input device 無効なオーディオ入力デバイス @@ -477,150 +477,156 @@ Format: 無効なオーディオ出力デバイス - + Invalid audio output device 無効なオーディオ出力デバイス - + Invalid PTT method 無効なPTT方式 - + Invalid PTT port 無効なPTT用ポート - - + + Invalid Contest Exchange 無効なコンテストナンバー - + You must input a valid ARRL Field Day exchange 正しいARRLフィールドデーコンテストナンバーを入力しなければなりません - + You must input a valid ARRL RTTY Roundup exchange 正しいARRL RTTY ラウンドアップのコンテストナンバーを入力しなければなりません - + Reset Decode Highlighting デコードハイライトをリセット - + Reset all decode highlighting and priorities to default values すべてのハイライトと優先順位設定をデフォルトへ戻す - + WSJT-X Decoded Text Font Chooser WSJT-Xのデコード出力用フォント選択 - + Load Working Frequencies 使用周波数を読み込み - - - + + + Frequency files (*.qrg);;All files (*.*) 周波数ファイル (*.qrg);;全ファイル (*.*) - + Replace Working Frequencies 使用周波数を置き換え - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? 本当に現在の周波数を読み込んだ周波数で置き換えてもいいですか? - + Merge Working Frequencies 使用周波数を追加併合 - - - + + + Not a valid frequencies file 正しい周波数ファイルではない - + Incorrect file magic 無効なファイルマジック - + Version is too new バージョンが新しすぎます - + Contents corrupt 中身が壊れています - + Save Working Frequencies 使用周波数を保存 - + Only Save Selected Working Frequencies 選択した使用周波数のみ保存 - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. 選択した使用周波数だけを保存してもいいですか。全部を保存したいときはNoをクリックしてください。 - + Reset Working Frequencies 使用周波数をリセット - + Are you sure you want to discard your current working frequencies and replace them with default ones? 本当に現在の使用周波数を破棄してデフォルト周波数と置き換えてもよいですか? - + Save Directory フォルダーを保存 - + AzEl Directory AzElフォルダー - + Rig control error 無線機コントロールエラー - + Failed to open connection to rig 無線機へ接続できません - + Rig failure 無線機エラー + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1443,22 +1449,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency 周波数を追加 - + IARU &Region: IARU地域(&R): - + &Mode: モード(&M): - + &Frequency (MHz): 周波数MHz(&F): @@ -1580,180 +1586,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Hamlib初期化エラー - + Hamlib settings file error: %1 at character offset %2 Hamlib設定ファイルエラー: %2にて%1 - + Hamlib settings file error: top level must be a JSON object ファイルのトップレベルはJSONオブジェクトでなければいけません - + Hamlib settings file error: config must be a JSON object Hamlib設定エラー: JSONオブジェクトでなければなりません - + Unsupported CAT type サポートしていないCATタイプ - + Hamlib error: %1 while %2 Hamlibエラー: %1 %2 - + opening connection to rig 無線機への接続 - + getting current frequency 現周波数を取得 - + getting current mode 現モードを取得 - - + + exchanging VFOs VFO入れ替え - - + + getting other VFO frequency もう一方のVFOの周波数を取得 - + getting other VFO mode もう一方のVFOのモードを取得 - - + + setting current VFO 現VFOを設定 - + getting frequency 周波数を取得 - + getting mode モードを取得 - - - + + + getting current VFO 現VFOを取得 - - - - + + + + getting current VFO frequency 現VFOの周波数を取得 - - - - - - + + + + + + setting frequency 周波数を設定 - - - - + + + + getting current VFO mode 現VFOのモードを取得 - - - - - + + + + + setting current VFO mode 現VFOモードを設定 - - + + setting/unsetting split mode スプリットのオン/オフ - - + + setting split mode スプリットモードオン - + setting split TX frequency and mode スプリット送信周波数とモードをセット - + setting split TX frequency スプリット送信周波数をセット - + getting split TX VFO mode スプリットモードを取得 - + setting split TX VFO mode スプリット送信VFOのモードをセット - + getting PTT state PTT状態を取得 - + setting PTT on PTTオン - + setting PTT off PTTオフ - + setting a configuration item コンフィグレーション項目をセット - + getting a configuration item コンフィグレーション項目を取得 @@ -2076,196 +2082,196 @@ Error(%2): %3 WSJT-X by K1JT - - - - - - - - + + + + + + + + Band Activity バンド状況 - - + + UTC dB DT Freq Dr UTC dB DT Freq Dr - - - - - - - + + + + + + + Rx Frequency 受信周波数 - + CQ only CQのみ - + Enter this QSO in log このQSOをログする - + Log &QSO QSOをログ(&Q) - + Stop monitoring モニター停止 - + &Stop 停止(&S) - + Toggle monitoring On/Off モニターオン/オフ - + &Monitor モニター(&M) - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>右側ウィンドウを消去. ダブルクリックで両側ウィンドウを消去.</p></body></html> - + Erase right window. Double-click to erase both windows. 右側ウィンドウを消去. ダブルクリックで両側ウィンドウを消去. - + &Erase 消去(&E) - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body><p>累加メッセージ平均をクリア.</p></body></html> - + Clear the accumulating message average. 累加メッセージ平均をクリア. - + Clear Avg 平均をクリア - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body><p>QSO周波数で最後に受信した信号をデコード</p></body></html> - + Decode most recent Rx period at QSO Frequency QSO周波数で最後に受信した信号をデコード - + &Decode デコード(&D) - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body><p>自動送信をオン/オフ</p></body></html> - + Toggle Auto-Tx On/Off 自動送信をオン/オフ - + E&nable Tx 送信許可(&n) - + Stop transmitting immediately 直ちに送信停止 - + &Halt Tx 送信停止(&H) - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>シングルトーンのオン/オフ</p></body></html> - + Toggle a pure Tx tone On/Off シングルトーンのオン/オフ - + &Tune チューン(&T) - + Menus メニュー - + Percentage of minute sequences devoted to transmitting. 送信に費やされた時間のパーセンテージ. - + Prefer Type 1 messages タイプ1メッセージ優先 - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>次回送信</p></body></html> - + USB dial frequency USBダイアル周波数 - + 14.078 000 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body><p>ノイズのみ受信のとき30dBが適当<br/>緑:適切<br/>赤:過大<br/>黄:過少</p></body></html> - + Rx Signal 受信信号 - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2276,344 +2282,344 @@ Yellow when too low 黄:過少 - + DX Call DXコール - + DX Grid DXグリッド - + Callsign of station to be worked 交信相手コールサイン - + Search for callsign in database データベース内でコールサイン検索 - + &Lookup 検索(&L) - + Locator of station to be worked 交信相手のロケータ - + Az: 251 16553 km Az: 251 16553 km - + Add callsign and locator to database データベースへコールサインとロケータを追加 - + Add 追加 - + Pwr 出力 - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body><p>黄色か赤色の場合無線機制御にエラーあり. リセットを押しダイヤル周波数を読み込む. Sはスプリット.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. 黄色か赤色の場合無線機制御にエラーあり. リセットを押しダイヤル周波数を読み込む. Sはスプリット. - + ? ? - + Adjust Tx audio level 送信オーディオレベル調整 - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body><p>バンドを選びMHz単位で周波数を入力するか差分をkHz単位(最後にkをつける)で入力.</p></body></html> - + Frequency entry 周波数入力 - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. バンドを選びMHz単位で周波数を入力するか差分をkHz単位(最後にkをつける)で入力. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body><p>デコードした文をダブルクリックしたときに送信周波数を動かさない.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. デコードした文をダブルクリックしたときに送信周波数を動かさない. - + Hold Tx Freq 送信周波数固定 - + Audio Rx frequency 受信オーディオ周波数 - - - - - + + + + + Hz Hz - - + + Rx Rx - - + + Set Tx frequency to Rx Frequency 送信周波数を受信周波数へコピー - + - + Frequency tolerance (Hz) 許容周波数(Hz) - - + + F Tol F Tol - - + + Set Rx frequency to Tx Frequency 受信周波数を送信周波数へコピー - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body><p>同期信号閾値. 小さい値ほど弱い同期信号を検出.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. 同期信号閾値. 小さい値ほど弱い同期信号を検出. - + Sync 同期 - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>短いメッセージフォーマットを使うときはチェック.</p></body></html> - + Check to use short-format messages. 短いメッセージフォーマットを使うときはチェック. - + Sh Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>JT9高速モードをオン</p></body></html> - + Check to enable JT9 fast modes JT9高速モードをオン - - + + Fast 高速 - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body><p>チェックすることで受信したメッセージに基づき自動的に送信メッセージを生成する.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. 受信メッセージに合わせて送信メッセージ自動生成. - + Auto Seq 自動シーケンス - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body><p>自分のCQに最初に応答してきた局をコール.</p></body></html> - + Check to call the first decoded responder to my CQ. 自分のCQに最初に応答してきた局をコール. - + Call 1st コール 1st - + Check to generate "@1250 (SEND MSGS)" in Tx6. Tx6に "@1250 (SEND MSGS)" を生成. - + Tx6 Tx6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body><p>チェックすると偶数分の0秒から送信開始.チェックを外すと奇数分.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. チェックすると偶数分の0秒から送信開始.チェックを外すと奇数分. - + Tx even/1st Tx even/1st - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body><p>現在の周波数からkHz上でCQをコール</p></body></html> - + Frequency to call CQ on in kHz above the current MHz 現在の周波数からkHz上でCQをコール - + Tx CQ Tx CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body><p>チェックすると &quot;Tx CQ&quot; 周波数でCQをコール. 受信は現在の周波数. 相手局がどの周波数で呼べばよいが分かるようにCQメッセージに現在の受信周波数を含める.</p><p>非標準コールには非対応.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. チェックすると "Tx CQ" 周波数でCQをコール. 受信は現在の周波数. 相手局がどの周波数で呼べばよいが分かるようにCQメッセージに現在の受信周波数を含める. 非標準コールには非対応. - + Rx All Freqs - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body><p>サブモードはトーン間隔を意味する.Aが一番狭い.</p></body></html> - + Submode determines tone spacing; A is narrowest. サブモードはトーン間隔を意味する.Aが一番狭い. - + Submode サブモード - - + + Fox Fox - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>Shメッセージをモニターする.</p></body></html> - + Check to monitor Sh messages. Shメッセージをモニターする. - + SWL SWL - + Best S+P Best S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body><p>ここをチェックして較正データを録音開始.<br/>測定中は較正処理は停止します.<br/>チェックをはずすと較正結果を見ることができます.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2622,204 +2628,214 @@ When not checked you can view the calibration results. チェックしないと較正結果を表示. - + Measure 測定 - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body><p>シグナルレポート: 2500Hzバンド幅におけるSN比(dB).</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). シグナルレポート: 2500Hzパスバンド幅におけるSN比(dB). - + Report レポート - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>送信/受信または周波数較正の時間</p></body></html> - + Tx/Rx or Frequency calibration sequence length Tx/Rxまたは周波数較正時間長 - - + + s s - - + + T/R T/R - + Toggle Tx mode 送信モードをトグル - + Tx JT9 @ - + Audio Tx frequency 送信オーディオ周波数 - - + + Tx Tx - + Tx# Tx# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body><p>ダブルクリックして次のQSOの待ち行列に加える.</p></body></html> - + + F High + + + + + F Low + + + + Double-click on another caller to queue that call for your next QSO. ダブルクリックで次のQSOで呼ぶ相手を待ち行列に追加. - + Next Call 次のコール - + 1 1 - - - + + + Send this message in next Tx interval このメッセージを次回送信する - + Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>このメッセージを次回送信する</p><p>ダブルクリックしてTx1メッセージとしてQSOを開始のオンオフ(タイプ1複合コールサインでは使えません)</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) >このメッセージを次回送信する. ダブルクリックしてTx1メッセージとしてQSOを開始のオンオフ(タイプ1複合コールサインでは使えません) - + Ctrl+1 - - - - + + + + Switch to this Tx message NOW このメッセージを送信 - + Tx &2 - + Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>このメッセージをすぐに送信</p><p>ダブルクリックすることでTx1メッセージを使うかどうか選択(タイプ1複合コールサインには使えません)</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) このメッセージをすぐに送信. ダブルクリックすることでTx1メッセージを使うかどうか選択(タイプ1複合コールサインには使えません) - + Tx &1 - + Alt+1 - + Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>このメッセージを次回送信</p><p>ダブルクリックして標準73メッセージにリセット</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message このメッセージを次回送信 ダブルクリックして標準73メッセージにリセット - + Ctrl+5 - + Ctrl+3 - + Tx &3 - + Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>このメッセージを次回送信</p><p>ダブルクリックするとTx4でRRRかRR73を送るかを切り替え(タイプ2複合コールサインでは使えません)</p><p>RR73 メッセージは、相手が確実にコピーしたと考えられるときに使ってください</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2828,17 +2844,17 @@ RR73 messages should only be used when you are reasonably confident that no mess RR73 メッセージは、相手が確実にコピーしたと考えられるときに使ってください - + Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>この送信メッセージをすぐに送信</p><p>ダブルクリックしてTx4のRRRとRR73を交互切り替え(タイプ2の複合コールサインでは使えません)</p><p>RR73は、双方ともメッセージを確認し、繰り返しが必要ないと考えうるときにのみ使いましょう</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2847,63 +2863,63 @@ RR73 messages should only be used when you are reasonably confident that no mess RR73 メッセージは、相手が確実にコピーしたと考えられるときに使ってください - + Tx &4 - + Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>このメッセージをすぐに送信</p><p>ダブルクリックして標準73メッセージにリセット</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message このメッセージをすぐに送信. ダブルクリックして標準73メッセージにリセット - + Tx &5 - + Alt+5 - + Now 送信 - + Generate standard messages for minimal QSO 最短QSO用メッセージを生成 - + Generate Std Msgs 標準メッセージ生成 - + Tx &6 - + Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2914,35 +2930,45 @@ ENTERを押してテキストを登録リストに追加. リストは設定(F2)で変更可能. - + Queue up the next Tx message 次の送信メッセージを待ち行列に追加 - + Next - + 2 - + Quick-Start Guide to FST4 and FST4W FST4とFST4Wのクイックスタートガイド - + FST4 FST4 - + FST4W FST4W + + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + Calling CQ CQをコール @@ -2952,8 +2978,8 @@ ENTERを押してテキストを登録リストに追加. CQメッセージ生成 - - + + CQ CQ @@ -2974,7 +3000,7 @@ ENTERを押してテキストを登録リストに追加. CQに応答するメッセージを生成 - + Grid グリッド @@ -3003,138 +3029,138 @@ ENTERを押してテキストを登録リストに追加. フリーテキスト - + Max dB 最大dB - + CQ AF - + CQ AN - + CQ AS - + CQ EU - + CQ NA - + CQ OC - + CQ SA - + CQ 0 - + CQ 1 - + CQ 2 - + CQ 3 - + CQ 4 - + CQ 5 - + CQ 6 - + CQ 7 - + CQ 8 - + CQ 9 - + Reset リセット - + N List リスト数 - + N Slots スロット数 - - - - - - - + + + + + + + Random ランダム - + Call - + S/N (dB) - + Distance 距離 - + More CQs これは何?チェックすると5回の送信に1回CQを出す @@ -3144,148 +3170,148 @@ ENTERを押してテキストを登録リストに追加. 2分の送信に費やすパーセンテージ. - - + + % % - + Tx Pct Tx Pct - + Band Hopping バンドホッピング - + Choose bands and times of day for band-hopping. バンドホッピングためのバンドと時間を選択. - + Schedule ... スケジュール .... - + 1/2 1/2 - + 2/2 2/2 - + 1/3 1/3 - + 2/3 2/3 - + 3/3 3/3 - + 1/4 1/4 - + 2/4 2/4 - + 3/4 3/4 - + 4/4 4/4 - + 1/5 1/5 - + 2/5 2/5 - + 3/5 3/5 - + 4/5 4/5 - + 5/5 5/5 - + 1/6 1/6 - + 2/6 2/6 - + 3/6 3/6 - + 4/6 4/6 - + 5/6 5/6 - + 6/6 6/6 - + Upload decoded messages to WSPRnet.org. デコードしたメッセージをWSPRnet.orgへアップロード. - + Upload spots スポットをアップロード - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>6桁のグリッドロケーターは2回のメッセージで送られます, 2回目のメッセージで6桁全部送られますが、コールサインはハッシュになります, 相手局は1回目であなたのコールサインをコピーしていなければなりません.. このオプションをチェックすると4桁のグリッドロケーターしか送らず、6桁のグリッドロケーターを送るための2回のメッセージ送信は行いません.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. 6桁のグリッドロケーターは2回のメッセージで送られます, 2回目のメッセージで6桁全部送られますが、コールサインはハッシュになります, 相手局は1回目であなたのコールサインをコピーしていなければなりません.. このオプションをチェックすると4桁のグリッドロケーターしか送らず、6桁のグリッドロケーターを送るための2回のメッセージ送信は行いません. @@ -3294,7 +3320,7 @@ ENTERを押してテキストを登録リストに追加. タイプ1メッセージを使う - + No own call decodes 自分のコールサインをデコードしない @@ -3303,62 +3329,62 @@ ENTERを押してテキストを登録リストに追加. 次の2分送信シーケンスの間に送信. - + Tx Next 次のTx - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. dBm単位の送信出力をWSPRメッセージに入れる. - + NB NB - + File ファイル - + View 表示 - + Decode デコード - + Save 保存 - + Help ヘルプ - + Mode モード - + Configurations コンフィグレーション - + Tools ツール - + Exit 終了 @@ -3367,87 +3393,87 @@ ENTERを押してテキストを登録リストに追加. コンフィグレーション - + About WSJT-X WSJT-Xについて - + Waterfall ウォーターフォール - + Open 開く - + Ctrl+O - + Open next in directory ディレクトリ中の次のファイルを開く - + Decode remaining files in directory ディレクトリ中の残りのファイルをデコード - + Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir SaveDirのすべての*.wavと*.c2ファイルを削除 - + None 無し - + Save all すべて保存 - + Online User Guide オンラインユーザーガイド - + Keyboard shortcuts キーボードショートカット - + Special mouse commands 特別なマウス操作 - + JT9 - + Save decoded デコードしたメッセージを保存 - + Normal 標準 - + Deep ディープ @@ -3456,12 +3482,12 @@ ENTERを押してテキストを登録リストに追加. 起動時モニターオフ - + Erase ALL.TXT ALL.TXTを消去 - + Erase wsjtx_log.adi wsjtx_log.adiを消去 @@ -3494,7 +3520,7 @@ ENTERを押してテキストを登録リストに追加. コールサインをダブルクリックして送信オン - + F7 @@ -3503,7 +3529,7 @@ ENTERを押してテキストを登録リストに追加. 73を送った後送信禁止 - + Runaway Tx watchdog Txウオッチドッグ発令 @@ -3516,12 +3542,12 @@ ENTERを押してテキストを登録リストに追加. 送信周波数を受信周波数にロック - + JT65 - + JT9+JT65 @@ -3534,147 +3560,147 @@ ENTERを押してテキストを登録リストに追加. DXCCエンティティと交信済みステータスを表示 - + Astronomical data 天文データ - + List of Type 1 prefixes and suffixes タイプ1プリフィックス、サフィックスのリスト - + Settings... 設定... - + Local User Guide 各国版ユーザーガイド - + Open log directory ログディレクトリを開く - + JT4 - + Message averaging メッセージ平均化 - + Enable averaging 平均化オン - + Enable deep search ディープサーチをオン - + WSPR WSPR - + Echo Graph エコーグラフ - + F8 - + Echo Echo - + EME Echo mode EMEエコーモード - + ISCAT - + Fast Graph 高速グラフ - + F9 - + &Download Samples ... サンプルをダウンロード(&D)... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>いろいろなモードのオーディオファイルをダウンロード.</p></body></html> - + MSK144 - + QRA64 - + Release Notes リリースノート - + Enable AP for DX Call DXコールのAPをオン - + FreqCal - + Measure reference spectrum 参照スペクトラムを測定 - + Measure phase response 位相応答を測定 - + Erase reference spectrum 参照スペクトラムを消去 - + Execute frequency calibration cycle 周波数較正実行 - + Equalization tools ... イコライザー... @@ -3687,48 +3713,48 @@ ENTERを押してテキストを登録リストに追加. 実験的LF/MFモード - + FT8 - - + + Enable AP AP使用 - + Solve for calibration parameters 較正パラメータ計算 - + Copyright notice 著作権表示 - + Shift+F1 - + Fox log Foxログ - + FT8 DXpedition Mode User Guide FT8 DXペディションモードユーザーガイド - + Reset Cabrillo log ... Cabrilloログをリセット... - + Color highlighting scheme ハイライト設定 @@ -3737,7 +3763,7 @@ ENTERを押してテキストを登録リストに追加. コンテストログ - + Export Cabrillo log ... Cabrilloログをエクスポート... @@ -3746,49 +3772,49 @@ ENTERを押してテキストを登録リストに追加. WSJT-X 2.0クイックスタートガイド - + Contest log コンテストログ - + Erase WSPR hashtable WSPRハッシュテーブルを消去 - + FT4 - + Rig Control Error 無線機制御エラー - - - + + + Receiving 受信中 - + Do you want to reconfigure the radio interface? 無線機インターフェイスを再構成しますか? - + %1 (%2 sec) audio frames dropped %1個 (%2 秒)のオーディオフレームが欠落 - + Audio Source オーディオソース - + Reduce system load システム負荷軽減 @@ -3797,194 +3823,194 @@ ENTERを押してテキストを登録リストに追加. サンプル大量欠落 - %1個 (%2秒)のオーディオフレームが欠落 - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 - + Error Scanning ADIF Log ADIFログスキャンエラー - + Scanned ADIF log, %1 worked before records created ADIFログ検索. %1交信済み記録作成しました - + Error Loading LotW Users Data LotWユーザデータをロードできません - + Error Writing WAV File WAVファイルを書き込みできません - + Enumerating audio devices - + Configurations... コンフィグレーション... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message メッセージ - + Error Killing jt9.exe Process jt9.exeプロセスを終了できません - + KillByName return code: %1 KillByNameリターンコード: %1 - + Error removing "%1" "%1"を削除できません - + Click OK to retry OKを押して再試行 - - + + Improper mode 不適切なモード - - + + File Open Error ファイルオープンエラー - - - - - + + + + + Cannot open "%1" for append: %2 "%2"を追加する"%1"が開けません - + Error saving c2 file c2ファイルを保存できません - + Error in Sound Input サウンド入力にエラー発生 - + Error in Sound Output サウンド出力にエラー発生 - - - + + + Single-Period Decodes シングルパスデコード - - - + + + Average Decodes 平均デコード - + Change Operator オペレータ交代 - + New operator: 新オペレータ: - + Status File Error ステータスファイルエラー - - + + Cannot open "%1" for writing: %2 %2を書き込むための"%1"が開けません - + Subprocess Error サブプロセスエラー - + Subprocess failed with exit code %1 サブプロセスエラー 終了コード %1 - + Running: %1 %2 実行中: %1 %2 - + Subprocess error サブプロセスエラー - + Reference spectrum saved 参照用スペクトラムを保存しました - + Invalid data in fmt.all at line %1 fmt.allの%1行目に無効なデータ - + Good Calibration Solution 較正良好 - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -3993,44 +4019,44 @@ ENTERを押してテキストを登録リストに追加. - + Delete Calibration Measurements 較正の測定結果を削除 - + The "fmt.all" file will be renamed as "fmt.bak" "fmt.all"は"fmt.bak"に名前が変わります - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." - + No data read from disk. Wrong file format? ディスクからデータが読めません.フォーマットが合っていますか? - + Confirm Delete 削除確認 - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? "%1"のすべての*.wavと*.c2ファイルを削除していいですか? - + Keyboard Shortcuts キーボードショートカット - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4217,12 +4243,12 @@ ENTERを押してテキストを登録リストに追加. </table> - + Special Mouse Commands 特別なマウス操作 - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4288,42 +4314,42 @@ ENTERを押してテキストを登録リストに追加. </table> - + No more files to open. これ以上開くファイルがありません. - + Spotting to PSK Reporter unavailable 現在PSK Reporterにスポットできません - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. 他の送信周波数を使ってください. WSJT-Xは30mバンドのWSPRサブバンド中の他のモードを受信せずに送信してしまいます. - + WSPR Guard Band WSPRガードバンド - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. 他のダイヤル周波数を使ってください. WSJT-XはFT8の標準サブバンドでFoxモードを使えません。 - + Fox Mode warning Foxモード警告 - + Last Tx: %1 最終送信: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4333,120 +4359,120 @@ To do so, check 'Special operating activity' and 設定|詳細タブで設定変更してください. - + Should you switch to ARRL Field Day mode? ARRLフィールドデーモードに切り替えますか? - + Should you switch to RTTY contest mode? RTTYコンテストモードに切り替えますか? - - - - + + + + Add to CALL3.TXT CALL3.TXTへ追加 - + Please enter a valid grid locator 有効なグリッドロケータを入力してください - + Cannot open "%1" for read/write: %2 %2を読み書きするための"%1"が開けません - + %1 is already in CALL3.TXT, do you wish to replace it? %1 がすでにCALL3.TXTにセットされています。置き換えますか? - + Warning: DX Call field is empty. 警告 DXコールが空白です. - + Log file error ログファイルエラー - + Cannot open "%1" "%1"を開けません - + Error sending log to N1MM N1MMへログを送れません - + Write returned "%1" 応答"%1"を書き込み - + Stations calling DXpedition %1 DXペディション %1を呼ぶ局 - + Hound Hound - + Tx Messages 送信メッセージ - - - + + + Confirm Erase 消去確認 - + Are you sure you want to erase file ALL.TXT? ALL.TXTファイルを消去してよいですか? - - + + Confirm Reset リセット確認 - + Are you sure you want to erase your contest log? コンテストログを消去していいですか? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. 現在のコンテストのQSO記録をすべて消去します。ADIFログには記録されますがCabrilloログにエクスポートすることはできません. - + Cabrillo Log saved Cabrilloログ保存しました - + Are you sure you want to erase file wsjtx_log.adi? wsjtx_log.adiを消してもよいですか? - + Are you sure you want to erase the WSPR hashtable? WSPRのハッシュテーブルを消してもよいですか? @@ -4455,60 +4481,60 @@ is already in CALL3.TXT, do you wish to replace it? VHF機能警告 - + Tune digital gain チューンのデジタルゲイン - + Transmit digital gain 送信デジタルゲイン - + Prefixes プリフィックス - + Network Error ネットワークエラー - + Error: %1 UDP server %2:%3 エラー %1 UDPサーバー %2:%3 - + File Error ファイルエラー - + Phase Training Disabled 位相調整オフ - + Phase Training Enabled 位相調整オン - + WD:%1m WD:%1m - - + + Log File Error ログファイルエラー - + Are you sure you want to clear the QSO queues? QSO待ち行列をクリアしてもいいですか? @@ -4855,22 +4881,21 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. オーディオ入力デバイスが開けません. - + An error occurred during read from the audio input device. オーディオ入力デバイスから読み込みエラー発生. - Audio data not being fed to the audio input device fast enough. - オーディオ入力デバイスにオーディオデータが入ってくる速度が遅すぎます. + オーディオ入力デバイスにオーディオデータが入ってくる速度が遅すぎます. - + Non-recoverable error, audio input device not usable at this time. 回復不能エラー. 現在オーディオ入力デバイスが使えません. @@ -4885,37 +4910,37 @@ Error(%2): %3 このオーディオ入力フォーマットはオーディオ入力デバイスでサポートされていません. - + Failed to initialize audio sink device オーディオ出力デバイス初期化エラー - + Idle 待機中 - + Receiving 受信中 - + Suspended サスペンド中 - + Interrupted 割り込まれました - + Error エラー - + Stopped 停止中 @@ -4923,67 +4948,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. オーディオ出力デバイスが開けません. - + An error occurred during write to the audio output device. オーディオ出力デバイスへデータ書き込みエラー発生. - + Audio data not being fed to the audio output device fast enough. 十分な速度でオーディオデータを出力デバイスへ送れません. - + Non-recoverable error, audio output device not usable at this time. 回復不能エラー. 現在オーディオ出力デバイスが使えません. - + Requested output audio format is not valid. このオーディオフォーマットは無効です. - + Requested output audio format is not supported on device. このオーディオフォーマットはオーディオ出力デバイスでサポートされていません. - + No audio output device configured. オーディオ出力デバイスが設定されていません. - + Idle 待機中 - + Sending 送信中 - + Suspended サスペンド中 - + Interrupted 割り込まれました - + Error エラー - + Stopped 停止中 @@ -4991,22 +5016,22 @@ Error(%2): %3 StationDialog - + Add Station 局を追加 - + &Band: バンド(&B): - + &Offset (MHz): オフセットMHz(&O): - + &Antenna: アンテナ(&A): @@ -5994,7 +6019,7 @@ radio interface behave as expected. サウンドカード - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -6011,46 +6036,46 @@ transmitting periods. 最後にアップロードしてから経過した日数 - + Select the audio CODEC to use for receiving. 受信用オーディオコーデックを選択. - + &Input: 入力(&I): - + Select the channel to use for receiving. 受信用チャンネルを選択. - - + + Mono モノラル - - + + Left - - + + Right - - + + Both 両方 - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -6065,7 +6090,7 @@ both here. VHFとサブモード機能をオン - + Ou&tput: 出力(&t): @@ -6320,67 +6345,67 @@ for assessing propagation and system performance. <html><head/><body><p>WSJT-Xがデータを送る先のUDPポート番号. ゼロの場合はデータを送りません.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p>オンにすると、WSJT-XはUDPサーバーからのデータを受け付けます.</p></body></html> - + Accept UDP requests UDP要求を受け付ける - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p>UDPリクエストを受け付けたことを表示. OSやウィンドウマネージャによって振る舞いが変わります. アプリウィンドウが最小化されていたり隠れていたりしていてもUDPリクエストが送られてきたことを知るために使うことができます.</p></body></html> - + Notify on accepted UDP request UDPリクエストが来たとき知らせる - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p>UDPリクエストが来たとき、ウィンドウを最小化から元の大きさへ戻します.</p></body></html> - + Accepted UDP request restores window ウィンドウを元に戻すUDPリクエストを受け付ける - + Secondary UDP Server (deprecated) 第二UDPサーバー(使わないことを推奨) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p>ここをチェックすると、WSJT-XはADIFフォーマットのログ情報を指定のホストの指定のポートへブロードキャストします. </p></body></html> - + Enable logged contact ADIF broadcast ADIFログ情報をブロードキャスト - + Server name or IP address: サーバー名またはIPアドレス: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>ADIF UDP ブロードキャストを受けるN1MM Logger+のホスト名. 通常は 'localhost' または ip アドレス 127.0.0.1</p><p>フォーマット:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">ホスト名</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 マルチキャストグループアドレス</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 マルチキャストグループアドレス</li></ul><p>空白にすることで、UDP経由のADIF情報ブロードキャストを停止.</p></body></html> - + Server port number: サーバーのポート番号: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>WSJT-XがADIF情報をブロードキャストする先のUDPポート番号. N1MM Logger+のときは2333. ゼロの場合はブロードキャスト停止.</p></body></html> @@ -6872,63 +6897,63 @@ Right click for insert and delete options. アプリのバージョン - + Another instance may be running おそらく他のインスタンスが動作中 - + try to remove stale lock file? 古いロックファイルの削除を試みますか? - + Failed to create a temporary directory 一時的作業ディレクトリーが作成できません - - + + Path: "%1" パス:"%1" - + Failed to create a usable temporary directory 一時的作業ディレクトリが作成できません - + Another application may be locking the directory おそらく他のアプリがディレクトリをロックしています - + Failed to create data directory データ用ディレクトリの作成ができません - + path: "%1" パス: "%1" - + Shared memory error 共有メモリエラー - + Unable to create shared memory segment 共有メモリセグメントが作成できません - + Sub-process error サブプロセスエラー - + Failed to close orphaned jt9 process jt9の孤立したプロセスを終了できません diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index e223501dc..a1677d2ce 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -368,75 +368,75 @@ Configuration::impl - - - + + + &Delete 删除(&D) - - + + &Insert ... 插入(&I) ... - + Failed to create save directory 无法创建保存目录 - + path: "%1% 目錄: "%1% - + Failed to create samples directory 无法创建示例目录 - + path: "%1" 目录: "%1" - + &Load ... 加载(&L) ... - + &Save as ... 另存为(&S) ... - + &Merge ... 合并(&M) ... - + &Reset 重置(&R) - + Serial Port: 串行端口: - + Serial port used for CAT control 用于CAT控制的串行端口 - + Network Server: 网络服务器: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -451,12 +451,12 @@ Formats: [IPv6-地址]:端口 - + USB Device: USB 设备: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -467,156 +467,162 @@ Format: [VID[:PID[:供应商[:产品]]]] - - + + Invalid audio input device 无效的音频输入设备 - + Invalid audio output device 无效的音频输出设备 - + Invalid PTT method 无效的PTT方法 - + Invalid PTT port 无效的PTT端口 - - + + Invalid Contest Exchange 无效的竞赛交换数据 - + You must input a valid ARRL Field Day exchange 您必须输入有效的 ARRL Field Day交换数据 - + You must input a valid ARRL RTTY Roundup exchange 您必须输入有效的 ARRL RTTY Roundup 交换数据 - + Reset Decode Highlighting 重置解码突出显示 - + Reset all decode highlighting and priorities to default values 将所有解码突出显示和优先级重置为默认值 - + WSJT-X Decoded Text Font Chooser WSJT-X 解码文本字体选择 - + Load Working Frequencies 载入工作频率 - - - + + + Frequency files (*.qrg);;All files (*.*) 频率文件 (*.qrg);;所有文件 (*.*) - + Replace Working Frequencies 替换工作频率 - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? 是否确实要放弃当前工作频率, 并将其替换为加载的频率? - + Merge Working Frequencies 合并工作频率 - - - + + + Not a valid frequencies file 不是有效的频率文件 - + Incorrect file magic 不正确的文件內容 - + Version is too new 版本太新 - + Contents corrupt 内容已损坏 - + Save Working Frequencies 保存工作频率 - + Only Save Selected Working Frequencies 仅保存选定的工作频率 - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. 是否确实要仅保存当前选择的工作频率? 单击 否 可保存所有. - + Reset Working Frequencies 重置工作频率 - + Are you sure you want to discard your current working frequencies and replace them with default ones? 您确定要放弃您当前的工作频率并用默认值频率替换它们吗? - + Save Directory 保存目录 - + AzEl Directory AzEl 目录 - + Rig control error 无线电设备控制错误 - + Failed to open connection to rig 无法打开无线电设备的连接 - + Rig failure 无线电设备故障 + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1433,22 +1439,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency 添加频率 - + IARU &Region: IA&RU 区域: - + &Mode: 模式(&M): - + &Frequency (MHz): 频率 (M&Hz): @@ -1570,180 +1576,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Hamlib 初始化错误 - + Hamlib settings file error: %1 at character offset %2 Hamlib 设置文件错误: %1 字符偏移量 %2 - + Hamlib settings file error: top level must be a JSON object Hamlib 设置文件错误: 顶层必须是 JSON 对象 - + Hamlib settings file error: config must be a JSON object Hamlib 设置文件错误: 配置必须是JSON对象 - + Unsupported CAT type 不支持 CAT 类型 - + Hamlib error: %1 while %2 Hamlib 错误: %1 当 %2 - + opening connection to rig 打开连接无线电设备 - + getting current frequency 获取当前频率 - + getting current mode 获取当前模式 - - + + exchanging VFOs 在 VFOs 之间切换 - - + + getting other VFO frequency 获取其他 VFO 频率 - + getting other VFO mode 获取其他 VFO 模式 - - + + setting current VFO 设置当前 VFO - + getting frequency 获取频率 - + getting mode 获取模式 - - - + + + getting current VFO 获取当前 VFO - - - - + + + + getting current VFO frequency 获取当前 VFO 频率 - - - - - - + + + + + + setting frequency 设置频率 - - - - + + + + getting current VFO mode 获取当前 VFO 模式 - - - - - + + + + + setting current VFO mode 设置当前 VFO 模式 - - + + setting/unsetting split mode 设置/取消 设置异频模式 - - + + setting split mode 设置异频模式 - + setting split TX frequency and mode 设置异频发射频率和模式 - + setting split TX frequency 设置异频发射频率 - + getting split TX VFO mode 获得异频发射 VFO 模式 - + setting split TX VFO mode 设置异频发射 VFO 模式 - + getting PTT state 获取PTT 状态 - + setting PTT on 设置PTT 开启 - + setting PTT off 设置PTT 关闭 - + setting a configuration item 设置配置项目 - + getting a configuration item 获取配置项目 @@ -2051,296 +2057,316 @@ Error(%2): %3 - - - - - - - - + + + + + + + + Band Activity 波段活动 - - + + UTC dB DT Freq Dr - - - - - - - + + + + + + + Rx Frequency 接收信息 - + CQ only 仅显示 CQ - + Enter this QSO in log 在日志中输入此通联纪录 - + Log &QSO 记录通联(&Q) - + Stop monitoring 停止监听 - + &Stop 停止(&S) - + Toggle monitoring On/Off 切换监听开/关 - + &Monitor 监听(&M) - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>擦除右窗口. 双击可擦除两个窗口.</p></body></html> - + Erase right window. Double-click to erase both windows. 擦除右窗口. 双击可擦除两个窗口. - + &Erase 擦除(&E) - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body><p>清除累积信息平均值.</p></body></html> - + Clear the accumulating message average. 清除累积信息平均值. - + Clear Avg 清除平均 - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body><p>在通联频率下解码最近的接收周期</p></body></html> - + Decode most recent Rx period at QSO Frequency 在通联频率下解码最近的接收周期 - + &Decode 解码(&D) - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body><p>切换自动发射 开/关</p></body></html> - + Toggle Auto-Tx On/Off 切换自动发射 开/关 - + E&nable Tx 启用发射(&n) - + Stop transmitting immediately 立即停止发射 - + &Halt Tx 停止发射(&H) - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>切换发射纯音调 开/关</p></body></html> - + Toggle a pure Tx tone On/Off 切换发射纯音调 开/关 - + &Tune 调谐(&T) - + Menus 菜单 - + + F High + + + + + F Low + + + + 1/2 - + 2/2 - + 1/3 - + 2/3 - + 3/3 - + 1/4 - + 2/4 - + 3/4 - + 4/4 - + 1/5 - + 2/5 - + 3/5 - + 4/5 - + 5/5 - + 1/6 - + 2/6 - + 3/6 - + 4/6 - + 5/6 - + 6/6 - + Percentage of minute sequences devoted to transmitting. 用于传输的分钟序列的百分比. - + Prefer Type 1 messages 首选类型 1 信息 - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>在下一个序列中传送.</p></body></html> - + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + + + USB dial frequency 上边带频率 - + 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body><p>当只存在噪音时建议30dB<br/>绿色好<br/>红色时可能发生剪切<br/>黄色时太低</p></body></html> - + Rx Signal 接收信号 - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2351,344 +2377,344 @@ Yellow when too low 黄色时太低 - + DX Call DX 呼号 - + DX Grid DX 网格 - + Callsign of station to be worked 正在通联的电台呼号 - + Search for callsign in database 在数据库中搜索此呼号的网格数据 - + &Lookup 检索(&L) - + Locator of station to be worked 通联中的电台定位 - + Az: 251 16553 km 角度: 251 16553 公里 - + Add callsign and locator to database 增加这呼号及网格的数据在数据库中 - + Add 增加 - + Pwr 功率 - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body><p>如果橙色或红色出现表示无线电设备控制故障, 请单击以重置并读取频率. S 表示异频模式.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. 如果橙色或红色出现表示无线电设备控制故障, 请单击以重置并读取频率. S 表示异频模式. - + ? - + Adjust Tx audio level 调整发射音频电平 - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body><p>选择工作频段或输入 MHz 频率或输入 kHz 增量,然后输入 k.</p></body></html> - + Frequency entry 输入频率 - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. 选择工作频段或输入兆赫频率或输入千赫增量, 然后输入 k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body><p>双击解码文本时, 选择以保持发射频率固定.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. 双击解码文本时, 选择以保持发射频率固定. - + Hold Tx Freq 保持发射频率 - + Audio Rx frequency 音频接收频率 - - - - - + + + + + Hz 赫兹 - - + + Rx 接收 - - + + Set Tx frequency to Rx Frequency 将发射频率设置为接收频率 - + - + Frequency tolerance (Hz) 频率容差 (赫兹) - - + + F Tol 容差 - - + + Set Rx frequency to Tx Frequency 将接收频率位置移往发射频率位置 - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body><p>同步阈值. 较低的数字接受较弱的同步信号.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. 同步阈值. 较低的数字接受较弱的同步信号. - + Sync 同步 - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>选择以使用短格式信息.</p></body></html> - + Check to use short-format messages. 选择以使用短格式信息. - + Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>选择以启用 JT9 快速模式</p></body></html> - + Check to enable JT9 fast modes 选择以启用 JT9 快速模式 - - + + Fast 快速 - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body><p>选择以启用基于收到的信息自动排序发射信息.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. 选择以启用基于收到的信息自动排序发射信息. - + Auto Seq 自动程序 - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body><p>选择以呼叫第一个解码的响应我的 CQ.</p></body></html> - + Check to call the first decoded responder to my CQ. 选择以呼叫第一个解码的响应我的 CQ. - + Call 1st 呼叫第一个解码 - + Check to generate "@1250 (SEND MSGS)" in Tx6. 选择以生成 "@1250 (发送信息)" 在发射6. - + Tx6 发射6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body><p>选择发射以偶数分钟或序列, 从 0 开始; 取消选择以奇数序列.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. 选择发射以偶数分钟或序列, 从 0 开始; 取消选择以奇数序列. - + Tx even/1st 发射偶数/第一 - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body><p>呼叫 CQ 的频率以 kHz 高于当前的 MHz</p></body></html> - + Frequency to call CQ on in kHz above the current MHz 呼叫 CQ 的频率以千赫高于当前的兆赫 - + Tx CQ 发射 CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body><p>选中此项, 以发射CQ呼叫. 接收将在当前频率上, CQ信息将显示在当前的接收信息窗口, 以便呼叫者知道回复的频率.</p><p>不适用于非标准呼号持有者.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. 选中此项, 以发射CQ呼叫. 接收将在当前频率上, CQ信息将显示在当前的接收信息窗口, 以便呼叫者知道回复的频率. 不适用于非标准呼号持有者. - + Rx All Freqs 接收全部频率 - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body><p>子模式確定音調間距; A 最窄.</p></body></html> - + Submode determines tone spacing; A is narrowest. 子模式確定音調間距; A 最窄. - + Submode 子模式 - - + + Fox 狐狸 - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>选择以监视速记信息.</p></body></html> - + Check to monitor Sh messages. 选择以监视速记信息. - + SWL - + Best S+P 最佳 S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body><p>选中可开始记录校准数据.<br/>当测量校准校正被禁用时.<br/>未检查时您可以查看校准结果.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2697,206 +2723,206 @@ When not checked you can view the calibration results. 未检查时您可以查看校准结果. - + Measure 测量 - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body><p>信号报告: 参考2500赫兹带宽 (分贝) 中的信噪比.</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). 信号报告: 参考2500赫兹带宽 (分贝) 中的信噪比. - + Report 报告 - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>发射/接收 或频率校准序列长度</p></body></html> - + Tx/Rx or Frequency calibration sequence length 发射/接收 或频率校准序列长度 - - + + s - - + + T/R - + Toggle Tx mode 切换发射模式 - + Tx JT9 @ 发射 JT9 @ - + Audio Tx frequency 音频发射频率 - - + + Tx 发射 - + Tx# 发射# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body><p>双击另一个呼号以排队呼叫您的下一个通联.</p></body></html> - + Double-click on another caller to queue that call for your next QSO. 双击另一个呼号以排队呼叫您的下一个通联. - + Next Call 下一个通联 - + 1 - - - + + + Send this message in next Tx interval 在下一个发射间隔内发送此信息 - + Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>在下一个发射间隔内发送此信息</p><p>双击以切换使用 发射 1 信息以启动和电台的通联 (不允许 1 型复合呼叫持有者)</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) 在下一个发射间隔内发送此信息 双击以切换使用 发射 1 信息以启动和电台的通联 (不允许 1 型复合呼叫持有者) - + Ctrl+1 - - - - + + + + Switch to this Tx message NOW 立即切换到此发射信息 - + Tx &2 发射 &2 - + Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>立即切换到此发射信息</p><p>双击以切换使用 发射 1 信息以启动和电台的通联 (不允许 1 型复合呼叫持有者)</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) 立即切换到此发射信息 双击以切换使用 发射 1 信息以启动和电台的通联 (不允许 1 型复合呼叫持有者) - + Tx &1 发射 &1 - + Alt+1 - + Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>在下一个发射间隔内发送此信息</p><p>双击可重置为标准 73 信息</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message 在下一个发射间隔内发送此信息 双击可重置为标准 73 信息 - + Ctrl+5 - + Ctrl+3 - + Tx &3 发射 &3 - + Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>在下一个发射间隔内发送此信息</p><p>双击可在 发射4 中的 RRR 和 RR73 信息之间切换 (不允许类型 2 复合呼叫持有者)</p><p>RR73 信息仅在您有理由相信不需要重复信息时才应使用</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2905,17 +2931,17 @@ RR73 messages should only be used when you are reasonably confident that no mess RR73 信息仅在您有理由相信不需要重复信息时才应使用 - + Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>立即切换到此发射信息</p><p>双击可在 发射 4 中的 RRR 和 RR73 信息之间切换 (不允许类型 2 复合呼叫持有者)</p><p>RR73 信息仅在您有理由相信不需要重复信息时才应使用</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2924,64 +2950,64 @@ RR73 messages should only be used when you are reasonably confident that no mess RR73 信息仅在您有理由相信不需要重复信息时才应使用 - + Tx &4 发射 &4 - + Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>立即切换到此发射信息</p><p>双击可重置为标准 73 信息</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message 立即切换到此发射信息 双击可重置为标准 73 信息 - + Tx &5 发射 &5 - + Alt+5 - + Now 现在 - + Generate standard messages for minimal QSO 生成标准信息用于通联 - + Generate Std Msgs 生成标准信息 - + Tx &6 发射 &6 - + Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2992,840 +3018,840 @@ list. The list can be maintained in Settings (F2). 列表. 该列表可在设置(F2)中维护. - + Queue up the next Tx message 排队下一个发射信息 - + Next 下一个 - + 2 - + Quick-Start Guide to FST4 and FST4W FST4和FST4W快速入门指南 - + FST4 - + FST4W - - + + CQ - + Grid 网格 - + Max dB 最大分贝 - + CQ AF CQ 非洲 - + CQ AN CQ 南极 - + CQ AS CQ 亚洲 - + CQ EU CQ 欧洲 - + CQ NA CQ 北美 - + CQ OC CQ 大洋洲 - + CQ SA CQ 南美 - + CQ 0 - + CQ 1 - + CQ 2 - + CQ 3 - + CQ 4 - + CQ 5 - + CQ 6 - + CQ 7 - + CQ 8 - + CQ 9 - + Reset 重置 - + N List N 列表 - + N Slots N 插槽 - - - - - - - + + + + + + + Random 随机 - + Call 呼号 - + S/N (dB) 信噪比(分贝) - + Distance 距离 - + More CQs 更多 CQ - - + + % - + Tx Pct 发射 Pct - + Band Hopping 波段预案 - + Choose bands and times of day for band-hopping. 选择波段和一天之中的时间进行波段跳跃. - + Schedule ... 时间流程 ... - + Upload decoded messages to WSPRnet.org. 将解码的信息上载到 WSPRnet.org. - + Upload spots 上传 spots - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>6 位定位器会导致发送 2 个不同的信息, 第二个包含完整定位器, 但只有哈希呼号. 其他电台必须解码第一个一次. 然后才能在第二个中解码您的呼叫. 如果此选项将避免两个信息协议. 则选中此选项仅发送 4 位定位器.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. 6 位定位器会导致发送 2 个不同的信息, 第二个包含完整定位器, 但只有哈希呼号. 其他电台必须解码第一个一次. 然后才能在第二个中解码您的呼叫. 如果此选项将避免两个信息协议. 则选中此选项仅发送 4 位定位器. - + No own call decodes 没有自己的呼号解码 - + Tx Next 发射下一个信息 - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. 将发射功率设置为 dBm (dB 高于 1 mW) 作为 WSPR 信息的一部分. - + NB - + File 文件 - + View 显示 - + Decode 解码 - + Save 保存 - + Help 帮助 - + Mode 模式 - + Configurations 配置 - + Tools 工具 - + Exit 关闭软件 - + About WSJT-X 关于 WSJT-X - + Waterfall 瀑布图 - + Open 打开文件 - + Ctrl+O - + Open next in directory 打开下一个文件 - + Decode remaining files in directory 打开余下文件 - + Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir 删除所有在SaveDir目录内 *.wav && *.c2 - + None 不保存 - + Save all 保存所有 - + Online User Guide 在线用户指南 - + Keyboard shortcuts 键盘快捷键 - + Special mouse commands 特殊鼠标动作 - + JT9 - + Save decoded 保存解码 - + Normal 正常 - + Deep 深度 - + Erase ALL.TXT 删除 ALL.TXT - + Erase wsjtx_log.adi 删除通联日志 wsjtx_log.adi - + F7 - + Runaway Tx watchdog 运行发射监管计时器 - + JT65 - + JT9+JT65 - + Astronomical data 天文数据 - + List of Type 1 prefixes and suffixes 类型 1 前缀和后缀的列表 - + Settings... 设置... - + Local User Guide 本地用户指南 - + Open log directory 打开日志文件目录 - + JT4 - + Message averaging 信息平均值 - + Enable averaging 平均值 - + Enable deep search 启用深度搜索 - + WSPR - + Echo Graph 回波图 - + F8 - + Echo - + EME Echo mode EME 回波模式 - + ISCAT - + Fast Graph 快速图 - + F9 - + &Download Samples ... 下载样本(&D) ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>下载演示各种模式的示例音频文件.</p></body></html> - + MSK144 - + QRA64 - + Release Notes 发行说明 - + Enable AP for DX Call 启用 AP 为 DX 呼叫 - + FreqCal - + Measure reference spectrum 测量参考频谱 - + Measure phase response 测量相位响应 - + Erase reference spectrum 擦除参考频谱 - + Execute frequency calibration cycle 执行频率校准周期 - + Equalization tools ... 均衡工具 ... - + FT8 - - + + Enable AP 启用 AP - + Solve for calibration parameters 校准参数的解算 - + Copyright notice 版权声明 - + Shift+F1 - + Fox log 狐狸日志 - + FT8 DXpedition Mode User Guide FT8 远征模式用户指南 - + Reset Cabrillo log ... 重置卡布里略日志 ... - + Color highlighting scheme 颜色突出显示方案 - + Export Cabrillo log ... 导出卡布里略日志 ... - + Contest log 竞赛日志 - + Erase WSPR hashtable 擦除 WSPR 哈希表 - + FT4 - + Rig Control Error 无线电设备控制错误 - - - + + + Receiving 接收 - + Do you want to reconfigure the radio interface? 是否要重新配置无线电设备接口? - + %1 (%2 sec) audio frames dropped %1 (%2 秒) 音频帧被丢弃 - + Audio Source 音频源 - + Reduce system load 降低系统负载 - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 样品丢失过多 - %1 (%2 sec) 音频帧在周期开始时丢失 %3 - + Error Scanning ADIF Log 扫描 ADIF 日志错误 - + Scanned ADIF log, %1 worked before records created 扫描 ADIF 日志, %1 创建曾经通联记录 - + Error Loading LotW Users Data 加载 LotW 用户数据错误 - + Error Writing WAV File 写入 WAV 文件时错误 - + Enumerating audio devices 列举音频设备 - + Configurations... 配置文件... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message 信息 - + Error Killing jt9.exe Process 错误终止 jt9.exe 进程 - + KillByName return code: %1 按名称终止返回代码: %1 - + Error removing "%1" 删除时错误 "%1" - + Click OK to retry 单击 确定 重试 - - + + Improper mode 模式不正确 - - + + File Open Error 文件打开错误 - - - - - + + + + + Cannot open "%1" for append: %2 无法打开 "%1" 用于附加: %2 - + Error saving c2 file 保存 c2 文件出错误 - + Error in Sound Input 声音输入出错误 - + Error in Sound Output 声音输出错误 - - - + + + Single-Period Decodes 单周期解码 - - - + + + Average Decodes 平均解码 - + Change Operator 改变操作员 - + New operator: 新操作员: - + Status File Error 状态文件错误 - - + + Cannot open "%1" for writing: %2 无法打开 "%1" 用于写入: %2 - + Subprocess Error 子流程出错误 - + Subprocess failed with exit code %1 子流程失败, 退出代码为 %1 - + Running: %1 %2 运行: %1 %2 - + Subprocess error 子进程错误 - + Reference spectrum saved 保存参考频谱 - + Invalid data in fmt.all at line %1 在 %1 行中 fmt.all 的无效数据 - + Good Calibration Solution 良好的校准解决方案 - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -3834,17 +3860,17 @@ list. The list can be maintained in Settings (F2). - + Delete Calibration Measurements 删除校准测量值 - + The "fmt.all" file will be renamed as "fmt.bak" "fmt.all" 文件将重命名为 "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -3853,62 +3879,62 @@ list. The list can be maintained in Settings (F2). "WSJT-X 的算法, 源代码, 外观和感觉及相关程序,和协议规格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版权 (C) 2001-2019 由以下一个或多个作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 开发组的其他成员." - + No data read from disk. Wrong file format? 没有从磁盘读取数据. 文件格式出错误? - + Confirm Delete 确认删除 - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? 是否确实要删除所有 *.wav 和 *.c2 文件在 "%1"? - + Keyboard Shortcuts 键盘快捷键 - + Special Mouse Commands 特殊鼠标组合 - + No more files to open. 没有要打开的文件. - + Spotting to PSK Reporter unavailable 无法发送至PSK Reporter - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. 请选择其他发射频率. WSJT-X 不会故意传输另一个模式在 WSPR 30米子波段上. - + WSPR Guard Band WSPR保护波段 - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. 请选择其它频率. WSJT-X 不会运行狐狸模式在标准 FT8 波段. - + Fox Mode warning 狐狸模式警告 - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -4002,7 +4028,7 @@ list. The list can be maintained in Settings (F2). </table> - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4067,12 +4093,12 @@ list. The list can be maintained in Settings (F2). </table> - + Last Tx: %1 最后发射: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4083,178 +4109,178 @@ To do so, check 'Special operating activity' and 设置高级选项卡上的 '欧洲 VHF 竞赛'. - + Should you switch to ARRL Field Day mode? 是否应切换到 ARRL Field Day 模式? - + Should you switch to RTTY contest mode? 是否应切换到 RTTY 竞赛模式? - - - - + + + + Add to CALL3.TXT 添加到 CALL3.TXT - + Please enter a valid grid locator 请输入有效的网格定位 - + Cannot open "%1" for read/write: %2 无法打开 "%1" 用于读/写: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? %1 已经在 CALL3.TXT, 你想替换它吗? - + Warning: DX Call field is empty. 警告: DX 呼号字段为空. - + Log file error 日志文件错误 - + Cannot open "%1" 无法打开 "%1" - + Error sending log to N1MM 将日志发送到 N1MM 时发生错误 - + Write returned "%1" 写入返回 "%1" - + Stations calling DXpedition %1 呼叫远征电台 %1 - + Hound 猎犬 - + Tx Messages 发射信息 - - - + + + Confirm Erase 确认擦除 - + Are you sure you want to erase file ALL.TXT? 是否确实要擦除 ALL.TXT 文件? - - + + Confirm Reset 确认重置 - + Are you sure you want to erase your contest log? 是否确实要擦除竞赛日志? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. 执行此操作将删除当前竞赛的所有通联记录. 它们将保留在 ADIF 日志文件中, 但无法导出到您的卡布里略日志中. - + Cabrillo Log saved 卡布里略日志已保存 - + Are you sure you want to erase file wsjtx_log.adi? 是否确实要擦除 wsjtx_log.adi 文件? - + Are you sure you want to erase the WSPR hashtable? 是否确实要擦除 WSPR 哈希表? - + Tune digital gain 调谐数码增益 - + Transmit digital gain 传输数码增益 - + Prefixes 前缀 - + Network Error 网络错误 - + Error: %1 UDP server %2:%3 错误: %1 UDP 服务器 %2:%3 - + File Error 文件错误 - + Phase Training Disabled 已禁用阶段训练 - + Phase Training Enabled 已启用阶段训练 - + WD:%1m - - + + Log File Error 日志文件错误 - + Are you sure you want to clear the QSO queues? 是否确实要清除通联队列? @@ -4597,22 +4623,21 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. 打开音频输入设备时错误. - + An error occurred during read from the audio input device. 从音频输入设备读取时错误. - Audio data not being fed to the audio input device fast enough. - 音频数据没有足够提供馈送到音频输入设备. + 音频数据没有足够提供馈送到音频输入设备. - + Non-recoverable error, audio input device not usable at this time. 不可恢复的错误, 音频输入设备此时不可用. @@ -4627,37 +4652,37 @@ Error(%2): %3 设备不支持请求输入的音频格式. - + Failed to initialize audio sink device 无法初始化音频接收器设备 - + Idle 闲置 - + Receiving 接收 - + Suspended 暂停 - + Interrupted 中断 - + Error 错误 - + Stopped 停止 @@ -4665,67 +4690,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. 打开音频输出设备时错误. - + An error occurred during write to the audio output device. 写入音频输出设备期间错误. - + Audio data not being fed to the audio output device fast enough. 音频数据未以足够快的速度馈送到音频输出设备. - + Non-recoverable error, audio output device not usable at this time. 不可恢复的错误, 音频输出设备此时不可用. - + Requested output audio format is not valid. 请求的输出音频格式无效. - + Requested output audio format is not supported on device. 设备不支持请求输出的音频格式. - + No audio output device configured. 未配置音频输出设备. - + Idle 闲置 - + Sending 发送 - + Suspended 暂停 - + Interrupted 中断 - + Error 错误 - + Stopped 停止 @@ -4733,22 +4758,22 @@ Error(%2): %3 StationDialog - + Add Station 添加电台 - + &Band: 波段(&B): - + &Offset (MHz): 偏移 (M&Hz): - + &Antenna: 天线(&A): @@ -5714,7 +5739,7 @@ radio interface behave as expected. 声效卡 - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -5732,46 +5757,46 @@ transmitting periods. 自上次上传以来的天数 - + Select the audio CODEC to use for receiving. 选择要用于接收的音频信号. - + &Input: 输入(&I): - + Select the channel to use for receiving. 选择要用于接收的通道. - - + + Mono 单声道 - - + + Left 左声道 - - + + Right 右声道 - - + + Both 双声道 - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -5787,7 +5812,17 @@ both here. 启用甚高频和子模式功能 - + + Data Bits + + + + + Stop Bits + + + + Ou&tput: 输出(&t): @@ -6032,67 +6067,67 @@ and DX Grid fields when a 73 or free text message is sent. <html><head/><body><p>输入 WSJT-X 应向其发送更新的 UDP 服务器的服务端口号. 如果为零, 将不会广播任何更新.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p>启用此功能后,WSJT-X 将接受来自接收解码消息的 UDP 服务器的某些请求.</p></body></html> - + Accept UDP requests 接受UDP请求 - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p>指示接受传入的 UDP 请求.此选项的效果因操作系统和窗口管理器而异,其目的是通知接受传入的 UDP 请求,即使此应用程序最小化或隐藏</p></body></html> - + Notify on accepted UDP request 接受UDP的请求时通知 - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p>如果接受 UDP 请求,则从最小化还原窗口.</p></body></html> - + Accepted UDP request restores window 接受UDP请求还原窗口 - + Secondary UDP Server (deprecated) 辅助 UDP 服务器 (已弃用) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p>选中后,WSJT-X 将以 ADIF 格式将记录的联系广播到配置的主机名和端口. </p></body></html> - + Enable logged contact ADIF broadcast 启用记录联系 ADIF 广播 - + Server name or IP address: 服务器名称或 IP 地址: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>N1MM Logger+ 程序的可选电脑主机, 用于接收 ADIF UDP 广播. 这通常是 'localhost' 或 IP地址 127.0.0.1</p><p>格式:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">主机名称</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 地址</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 多播组地址</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 多播组地址</li></ul><p>清除此字段将禁用通过 UDP 广播 ADIF 信息.</p></body></html> - + Server port number: 服务器端口号: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>输入 WSJT-X 应用于 ADIF 日志信息的 UDP 广播的端口号. 对于 N1MM Logger+, 此值应为 2333. 如果为零, 将不会广播任何更新.</p></body></html> @@ -6536,63 +6571,63 @@ Right click for insert and delete options. main - + Another instance may be running 另一个应用程序可能正在运行 - + try to remove stale lock file? 尝试删除陈旧的锁文件? - + Failed to create a temporary directory 无法创建临时目录 - - + + Path: "%1" 目录: "%1" - + Failed to create a usable temporary directory 无法创建可用的临时目录 - + Another application may be locking the directory 另一个应用程序可能正在锁定目录 - + Failed to create data directory 无法创建数据目录 - + path: "%1" 目录: "%1" - + Shared memory error 共享内存错误 - + Unable to create shared memory segment 无法创建共享内存段 - + Sub-process error 子进程错误 - + Failed to close orphaned jt9 process 无法关闭遗留的jt9进程 diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index 35b7e60c5..9e17f02eb 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -368,75 +368,75 @@ Configuration::impl - - - + + + &Delete 刪除(&D) - - + + &Insert ... 插入(&I) ... - + Failed to create save directory 無法建立儲存目錄 - + path: "%1% 目錄: "%1% - + Failed to create samples directory 無法建立範例目錄 - + path: "%1" 目錄: "%1" - + &Load ... 載入(&L)... - + &Save as ... 另存為(&S) ... - + &Merge ... 合併(&M) ... - + &Reset 重置(&R) - + Serial Port: 串行端口: - + Serial port used for CAT control 用於CAT控制的串行端口 - + Network Server: 網絡服務器: - + Optional hostname and port of network service. Leave blank for a sensible default on this machine. Formats: @@ -451,12 +451,12 @@ Formats: [IPv6-地址]:端口 - + USB Device: USB設備: - + Optional device identification. Leave blank for a sensible default for the rig. Format: @@ -467,156 +467,162 @@ Format: [VID[:PID[:供應商[:產品]]]] - - + + Invalid audio input device 無效的音頻輸入設備 - + Invalid audio output device 無效的音頻輸出設備 - + Invalid PTT method 無效的PTT方法 - + Invalid PTT port 無效的PTT端口 - - + + Invalid Contest Exchange 無效的競賽交換數據 - + You must input a valid ARRL Field Day exchange 您必須輸入有效的 ARRL Field Day交換數據 - + You must input a valid ARRL RTTY Roundup exchange 您必須輸入有效的 ARRL RTTY Roundup 交換數據 - + Reset Decode Highlighting 重置解碼突出顯示 - + Reset all decode highlighting and priorities to default values 將所有解碼突出顯示和優先順序重置為預設值 - + WSJT-X Decoded Text Font Chooser WSJT-X 解碼文本字體選擇 - + Load Working Frequencies 載入工作頻率 - - - + + + Frequency files (*.qrg);;All files (*.*) 頻率檔案 (*.qrg);;所有檔案 (*.*) - + Replace Working Frequencies 替換工作頻率 - + Are you sure you want to discard your current working frequencies and replace them with the loaded ones? 是否確實要放棄當前工作頻率, 並將其替換為載入的頻率? - + Merge Working Frequencies 合併工作頻率 - - - + + + Not a valid frequencies file 不是有效的頻率檔案 - + Incorrect file magic 不正確的檔案內容 - + Version is too new 版本太新 - + Contents corrupt 內容已損壞 - + Save Working Frequencies 儲存工作頻率 - + Only Save Selected Working Frequencies 只儲存選取的工作頻率 - + Are you sure you want to save only the working frequencies that are currently selected? Click No to save all. 是否確定要只儲存目前選擇的工作頻率? 按一下 否 可儲存所有. - + Reset Working Frequencies 重置工作頻率 - + Are you sure you want to discard your current working frequencies and replace them with default ones? 您確定要放棄您當前的工作頻率並用默認值頻率替換它們嗎? - + Save Directory 儲存目錄 - + AzEl Directory AzEl 目錄 - + Rig control error 無線電設備控制錯誤 - + Failed to open connection to rig 無法開啟無線電設備的連接 - + Rig failure 無線電設備故障 + + + Not found + audio device missing + + DXLabSuiteCommanderTransceiver @@ -1433,22 +1439,22 @@ Error: %2 - %3 FrequencyDialog - + Add Frequency 添加頻率 - + IARU &Region: IA&RU 區域: - + &Mode: 模式(&M): - + &Frequency (MHz): 頻率 (M&Hz): @@ -1570,180 +1576,180 @@ Error: %2 - %3 HamlibTransceiver - - + + Hamlib initialisation error Hamlib 初始化錯誤 - + Hamlib settings file error: %1 at character offset %2 Hamlib 設置檔案錯誤: %1 字符偏移量 %2 - + Hamlib settings file error: top level must be a JSON object Hamlib 設置檔案錯誤: 頂層必須是 JSON 對象 - + Hamlib settings file error: config must be a JSON object Hamlib 設置檔案錯誤: 配置必須是JSON對象 - + Unsupported CAT type 不支持 CAT 類型 - + Hamlib error: %1 while %2 Hamlib 錯誤: %1 當 %2 - + opening connection to rig 開啟連接無線電設備 - + getting current frequency 獲取當前頻率 - + getting current mode 獲取當前模式 - - + + exchanging VFOs 在 VFOs 之間切換 - - + + getting other VFO frequency 獲取其他 VFO 頻率 - + getting other VFO mode 獲取其他 VFO 模式 - - + + setting current VFO 設置當前 VFO - + getting frequency 獲取頻率 - + getting mode 獲取模式 - - - + + + getting current VFO 獲取當前 VFO - - - - + + + + getting current VFO frequency 獲取當前 VFO 頻率 - - - - - - + + + + + + setting frequency 設置頻率 - - - - + + + + getting current VFO mode 獲取當前 VFO 模式 - - - - - + + + + + setting current VFO mode 設置當前 VFO 模式 - - + + setting/unsetting split mode 設置/取消 設置異頻模式 - - + + setting split mode 設置異頻模式 - + setting split TX frequency and mode 設置異頻發射頻率和模式 - + setting split TX frequency 設置異頻發射頻率 - + getting split TX VFO mode 獲得異頻發射 VFO 模式 - + setting split TX VFO mode 設置異頻發射 VFO 模式 - + getting PTT state 獲取PTT 狀態 - + setting PTT on 設置PTT 開啟 - + setting PTT off 設置PTT 關閉 - + setting a configuration item 設置配置項目 - + getting a configuration item 獲取配置項目 @@ -2051,296 +2057,316 @@ Error(%2): %3 - - - - - - - - + + + + + + + + Band Activity 波段活動 - - + + UTC dB DT Freq Dr - - - - - - - + + + + + + + Rx Frequency 接收信息 - + CQ only 只顯示 CQ - + Enter this QSO in log 在日誌中輸入此通聯紀錄 - + Log &QSO 記錄通聯(&Q) - + Stop monitoring 停止監聽 - + &Stop 停止(&S) - + Toggle monitoring On/Off 切換監聽開/關 - + &Monitor 監聽(&M) - + <html><head/><body><p>Erase right window. Double-click to erase both windows.</p></body></html> <html><head/><body><p>擦除右視窗. 雙擊可擦除兩個視窗.</p></body></html> - + Erase right window. Double-click to erase both windows. 擦除右視窗. 雙擊可擦除兩個視窗. - + &Erase 擦除(&E) - + <html><head/><body><p>Clear the accumulating message average.</p></body></html> <html><head/><body><p>清除累積信息平均值.</p></body></html> - + Clear the accumulating message average. 清除累積信息平均值. - + Clear Avg 清除平均 - + <html><head/><body><p>Decode most recent Rx period at QSO Frequency</p></body></html> <html><head/><body><p>在通聯頻率下解碼最近的接收週期</p></body></html> - + Decode most recent Rx period at QSO Frequency 在通聯頻率下解碼最近的接收週期 - + &Decode 解碼(&D) - + <html><head/><body><p>Toggle Auto-Tx On/Off</p></body></html> <html><head/><body><p>切換自動發射 開/關</p></body></html> - + Toggle Auto-Tx On/Off 切換自動發射 開/關 - + E&nable Tx 啟用發射(&n) - + Stop transmitting immediately 立即停止發射 - + &Halt Tx 停止發射(&H) - + <html><head/><body><p>Toggle a pure Tx tone On/Off</p></body></html> <html><head/><body><p>切換發射純音調 開/關</p></body></html> - + Toggle a pure Tx tone On/Off 切換發射純音調 開/關 - + &Tune 調諧(&T) - + Menus 選單 - + + F High + + + + + F Low + + + + 1/2 - + 2/2 - + 1/3 - + 2/3 - + 3/3 - + 1/4 - + 2/4 - + 3/4 - + 4/4 - + 1/5 - + 2/5 - + 3/5 - + 4/5 - + 5/5 - + 1/6 - + 2/6 - + 3/6 - + 4/6 - + 5/6 - + 6/6 - + Percentage of minute sequences devoted to transmitting. 用於傳輸的分鐘序列的百分比. - + Prefer Type 1 messages 首選類型 1 資訊 - + <html><head/><body><p>Transmit during the next sequence.</p></body></html> <html><head/><body><p>在下一個序列中傳送.</p></body></html> - + + SWL Mode + + + + + Hide lower panel controls to maximize deocde windows + + + + USB dial frequency 上邊帶頻率 - + 14.078 000 - + <html><head/><body><p>30dB recommended when only noise present<br/>Green when good<br/>Red when clipping may occur<br/>Yellow when too low</p></body></html> <html><head/><body><p>當只存在噪音時建議30dB<br/>綠色好<br/>紅色時可能發生剪切<br/>黃色時太低</p></body></html> - + Rx Signal 接收信號 - + 30dB recommended when only noise present Green when good Red when clipping may occur @@ -2351,344 +2377,344 @@ Yellow when too low 黃色時太低 - + DX Call DX 呼號 - + DX Grid DX 網格 - + Callsign of station to be worked 正在通聯的電臺呼號 - + Search for callsign in database 在數據庫中搜索此呼號的網格數據 - + &Lookup 檢索(&L) - + Locator of station to be worked 通聯中的電臺定位 - + Az: 251 16553 km 角度: 251 16553 公里 - + Add callsign and locator to database 增加這呼號及網格的數據在數據庫中 - + Add 增加 - + Pwr 功率 - + <html><head/><body><p>If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode.</p></body></html> <html><head/><body><p>如果橙色或紅色出現表示無線電設備控制故障, 請單擊以重置並讀取頻率. S 表示異頻模式.</p></body></html> - + If orange or red there has been a rig control failure, click to reset and read the dial frequency. S implies split mode. 如果橙色或红色出现表示无线电设备控制故障, 请单击以重置并读取频率. S 表示异频模式. - + ? - + Adjust Tx audio level 調整發射音效電平 - + <html><head/><body><p>Select operating band or enter frequency in MHz or enter kHz increment followed by k.</p></body></html> <html><head/><body><p>選擇工作頻段或輸入 MHz 頻率或輸入 kHz 增量,然後輸入 k.</p></body></html> - + Frequency entry 輸入頻率 - + Select operating band or enter frequency in MHz or enter kHz increment followed by k. 選擇工作頻段或輸入 MHz 頻率或輸入 kHz 增量,然後輸入 k. - + <html><head/><body><p align="center"> 2015 Jun 17 </p><p align="center"> 01:23:45 </p></body></html> - + <html><head/><body><p>Check to keep Tx frequency fixed when double-clicking on decoded text.</p></body></html> <html><head/><body><p>按兩下解碼文字時, 選擇以保持發射頻率固定.</p></body></html> - + Check to keep Tx frequency fixed when double-clicking on decoded text. 按兩下解碼文字時, 選擇以保持發射頻率固定. - + Hold Tx Freq 保持發射頻率 - + Audio Rx frequency 音頻接收頻率 - - - - - + + + + + Hz 赫茲 - - + + Rx 接收 - - + + Set Tx frequency to Rx Frequency 將發射頻率設定為接收頻率 - + - + Frequency tolerance (Hz) 頻率容差 (赫兹) - - + + F Tol 容差 - - + + Set Rx frequency to Tx Frequency 將接收頻率位置移往發射頻率位置 - + - + <html><head/><body><p>Synchronizing threshold. Lower numbers accept weaker sync signals.</p></body></html> <html><head/><body><p>同步閾值. 較低的數位接受較弱的同步訊號.</p></body></html> - + Synchronizing threshold. Lower numbers accept weaker sync signals. 同步閾值. 較低的數位接受較弱的同步訊號. - + Sync 同步 - + <html><head/><body><p>Check to use short-format messages.</p></body></html> <html><head/><body><p>選擇以使用短格式信息.</p></body></html> - + Check to use short-format messages. 選擇以使用短格式信息. - + Sh - + <html><head/><body><p>Check to enable JT9 fast modes</p></body></html> <html><head/><body><p>選擇以開啟 JT9 快速模式</p></body></html> - + Check to enable JT9 fast modes 選擇以開啟 JT9 快速模式 - - + + Fast 快速 - + <html><head/><body><p>Check to enable automatic sequencing of Tx messages based on received messages.</p></body></html> <html><head/><body><p>選擇以開啟接收到信息自動排序發射信息.</p></body></html> - + Check to enable automatic sequencing of Tx messages based on received messages. 選擇以開啟接收到信息自動排序發射信息. - + Auto Seq 自動程序 - + <html><head/><body><p>Check to call the first decoded responder to my CQ.</p></body></html> <html><head/><body><p>選擇以呼叫第一個解碼的回應器到我的 CQ.</p></body></html> - + Check to call the first decoded responder to my CQ. 選擇以呼叫第一個解碼的回應我的 CQ. - + Call 1st 呼叫第一個解碼 - + Check to generate "@1250 (SEND MSGS)" in Tx6. 選擇以產生 "@1250 (傳送信息)" 在發射6. - + Tx6 發射6 - + <html><head/><body><p>Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences.</p></body></html> <html><head/><body><p>選擇發射以偶數分鐘或序列, 從 0 開始; 取消選擇以奇數序列.</p></body></html> - + Check to Tx in even-numbered minutes or sequences, starting at 0; uncheck for odd sequences. 選擇發射以偶數分鐘或序列, 從 0 開始; 取消選擇以奇數序列. - + Tx even/1st 發射偶數/第一 - + <html><head/><body><p>Frequency to call CQ on in kHz above the current MHz</p></body></html> <html><head/><body><p>呼叫CQ 的頻率以 kHz 高於目前的 MHz</p></body></html> - + Frequency to call CQ on in kHz above the current MHz 呼叫 CQ 的頻率以千赫高於目前的兆赫 - + Tx CQ 發射 CQ - + <html><head/><body><p>Check this to call CQ on the &quot;Tx CQ&quot; frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on.</p><p>Not available to nonstandard callsign holders.</p></body></html> <html><head/><body><p>勾選此項, 以發射CQ呼叫. 接收將在當前頻率上,CQ信息將顯示在當前的接收資訊視窗, 以便呼叫者知道回覆的頻率.</p><p> 不適用於非標準呼號持有者.</p></body></html> - + Check this to call CQ on the "Tx CQ" frequency. Rx will be on the current frequency and the CQ message wiill include the current Rx frequency so callers know which frequency to reply on. Not available to nonstandard callsign holders. 勾選此項, 以發射CQ呼叫. 接收將在當前頻率上,CQ信息將顯示在當前的接收資訊視窗, 以便呼叫者知道回覆的頻率. 不適用於非標準呼號持有者. - + Rx All Freqs 接收所有頻率 - + <html><head/><body><p>Submode determines tone spacing; A is narrowest.</p></body></html> <html><head/><body><p>子模式確定音調間距; A 最窄.</p></body></html> - + Submode determines tone spacing; A is narrowest. 子模式確定音調間距; A 最窄. - + Submode 子模式 - - + + Fox 狐狸 - + <html><head/><body><p>Check to monitor Sh messages.</p></body></html> <html><head/><body><p>選擇以監視速記信息.</p></body></html> - + Check to monitor Sh messages. 選擇以監視速記信息. - + SWL - + Best S+P 最佳 S+P - + <html><head/><body><p>Check this to start recording calibration data.<br/>While measuring calibration correction is disabled.<br/>When not checked you can view the calibration results.</p></body></html> <html><head/><body><p>勾選可開始紀錄校準資料.<br/>當測量校準校正被禁用時.<br/>未檢查時您可以查看校準結果.</p></body></html> - + Check this to start recording calibration data. While measuring calibration correction is disabled. When not checked you can view the calibration results. @@ -2697,206 +2723,206 @@ When not checked you can view the calibration results. 未檢查時您可以查看校準結果. - + Measure 測量 - + <html><head/><body><p>Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB).</p></body></html> <html><head/><body><p>信號報告: 參考2500赫兹頻寬 (dB) 中的信噪比.</p></body></html> - + Signal report: Signal-to-noise ratio in 2500 Hz reference bandwidth (dB). 信號報告: 參考2500赫兹頻寬 (dB) 中的信噪比. - + Report 報告 - + <html><head/><body><p>Tx/Rx or Frequency calibration sequence length</p></body></html> <html><head/><body><p>發射/接收 或頻率校準序列長度</p></body></html> - + Tx/Rx or Frequency calibration sequence length 發射/接收 或頻率校準序列長度 - - + + s - - + + T/R - + Toggle Tx mode 切換發射模式 - + Tx JT9 @ 發射 JT9 @ - + Audio Tx frequency 音訊發射頻率 - - + + Tx 發射 - + Tx# 發射# - + <html><head/><body><p>Double-click on another caller to queue that call for your next QSO.</p></body></html> <html><head/><body><p>按兩下另一個呼號以排隊呼叫您的下一個通聯.</p></body></html> - + Double-click on another caller to queue that call for your next QSO. 按兩下另一個呼號以排隊呼叫您的下一個通聯. - + Next Call 下一個通聯 - + 1 - - - + + + Send this message in next Tx interval 在下一個發射間隔內發送此信息 - + Ctrl+2 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>在下一個發射間隔中傳送此訊息</p><p>按兩下以切換使用 發射 1 訊息以啟動電臺的通聯 (不允許 1 型複合呼叫持有者)<</p></body></html> - + Send this message in next Tx interval Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) 在下一個發射間隔中傳送此訊息 按兩下以切換使用 發射 1 訊息以啟動電臺的通聯 (不允許 1 型複合呼叫持有者) - + Ctrl+1 - - - - + + + + Switch to this Tx message NOW 立即切換到此發射信息 - + Tx &2 發射 &2 - + Alt+2 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders)</p></body></html> <html><head/><body><p>立即切換到此發射信息</p><p>按兩下以切換使用 發射 1 訊息以啟動電臺的通聯 (不允許 1 型複合呼叫持有者)</p></body></html> - + Switch to this Tx message NOW Double click to toggle the use of the Tx1 message to start a QSO with a station (not allowed for type 1 compound call holders) 立即切換到此發射信息 按兩下以切換使用 發射 1 訊息以啟動電臺的通聯 (不允許 1 型複合呼叫持有者) - + Tx &1 發射 &1 - + Alt+1 - + Ctrl+6 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>在下一個發射間隔內傳送此信息</p><p>雙擊可重置為標準 73 信息</p></body></html> - + Send this message in next Tx interval Double-click to reset to the standard 73 message 在下一個發射間隔內傳送此信息 雙擊可重置為標準 73 信息 - + Ctrl+5 - + Ctrl+3 - + Tx &3 發射 &3 - + Alt+3 - + <html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>在下一個發射間隔內傳送此信息</p><p>按兩下可在 發射4 中的 RRR 和 RR73 信息之間切換 (不允許類型 2 複合呼叫持有者)</p><p>RR73 信息僅在您有理由相信不需要重複信息時才應使用</p></body></html> - + Send this message in next Tx interval Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type 2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2905,17 +2931,17 @@ RR73 messages should only be used when you are reasonably confident that no mess RR73 信息僅在您有理由相信不需要重複信息時才應使用 - + Ctrl+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders)</p><p>RR73 messages should only be used when you are reasonably confident that no message repetitions will be required</p></body></html> <html><head/><body><p>立即切換到此發射信息</p><p>按兩下可在 發射 4 中的 RRR 和 RR73 信息之間切換 (不允許類型 2 複合呼叫持有者)</p><p>RR73 信息僅在您有理由相信不需要重複信息時才應使用</p></body></html> - + Switch to this Tx message NOW Double-click to toggle between RRR and RR73 messages in Tx4 (not allowed for type2 compound call holders) RR73 messages should only be used when you are reasonably confident that no message repetitions will be required @@ -2924,64 +2950,64 @@ RR73 messages should only be used when you are reasonably confident that no mess RR73 信息僅在您有理由相信不需要重複信息時才應使用 - + Tx &4 發射 &4 - + Alt+4 - + <html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html> <html><head/><body><p>立即切换到此发射信息</p><p>雙擊可重置為標準 73 信息</p></body></html> - + Switch to this Tx message NOW Double-click to reset to the standard 73 message 立即切换到此发射信息 雙擊可重置為標準 73 信息 - + Tx &5 發射 &5 - + Alt+5 - + Now 現在 - + Generate standard messages for minimal QSO 產生標準信息用於通聯 - + Generate Std Msgs 產生標準信息 - + Tx &6 發射 &6 - + Alt+6 - + Enter a free text message (maximum 13 characters) or select a predefined macro from the dropdown list. Press ENTER to add the current text to the predefined @@ -2992,840 +3018,840 @@ list. The list can be maintained in Settings (F2). 清單. 該清單可在設定(F2)中維護. - + Queue up the next Tx message 排到下一個發射信息 - + Next 下一個 - + 2 - + Quick-Start Guide to FST4 and FST4W FST4和FST4W快速入門指南 - + FST4 - + FST4W - - + + CQ - + Grid 網格 - + Max dB 最大分貝 - + CQ AF CQ 非洲 - + CQ AN CQ 南極 - + CQ AS CQ 亞洲 - + CQ EU CQ 歐洲 - + CQ NA CQ 北美 - + CQ OC CQ 大洋洲 - + CQ SA CQ 南美 - + CQ 0 - + CQ 1 - + CQ 2 - + CQ 3 - + CQ 4 - + CQ 5 - + CQ 6 - + CQ 7 - + CQ 8 - + CQ 9 - + Reset 重置 - + N List N 清單 - + N Slots N 插槽 - - - - - - - + + + + + + + Random 隨機 - + Call 呼號 - + S/N (dB) 信噪比(分貝) - + Distance 距離 - + More CQs 更多 CQ - - + + % - + Tx Pct 發射 Pct - + Band Hopping 波段預案 - + Choose bands and times of day for band-hopping. 選擇波段和一天之中的時間進行波段跳躍. - + Schedule ... 時間流程 ... - + Upload decoded messages to WSPRnet.org. 將解碼的信息上載到 WSPRnet.org. - + Upload spots 上傳 spots - + <html><head/><body><p>6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol.</p></body></html> <html><head/><body><p>6 位定位器會導致發送 2 個不同的信息, 第二個包含完整定位器, 但只有哈希呼號,其他電臺必須解碼第一個一次, 然後才能在第二個中解碼您的呼叫. 如果此選項將避免兩個信息協定, 則選中此選項僅發送 4 位定位器.</p></body></html> - + 6 digit locators cause 2 different messages to be sent, the second contains the full locator but only a hashed callsign, other stations must have decoded the first once before they can decode your call in the second. Check this option to only send 4 digit locators if it will avoid the two message protocol. 6 位定位器會導致發送 2 個不同的信息, 第二個包含完整定位器, 但只有哈希呼號,其他電臺必須解碼第一個一次, 然後才能在第二個中解碼您的呼叫. 如果此選項將避免兩個信息協定, 則選中此選項僅發送 4 位定位器. - + No own call decodes 沒有自己的呼號解碼 - + Tx Next 發射下一個信息 - + Set Tx power in dBm (dB above 1 mW) as part of your WSPR message. 將發射功率設置為 dBm (dB 高於 1 mW) 作為 WSPR 信息的一部分. - + NB - + File 檔案 - + View 顯示 - + Decode 解碼 - + Save 儲存 - + Help 說明 - + Mode 模式 - + Configurations 設定 - + Tools 工具 - + Exit 關閉軟件 - + About WSJT-X 有關 WSJT-X - + Waterfall 瀑布圖 - + Open 開啟檔案 - + Ctrl+O - + Open next in directory 開啟下一個檔案 - + Decode remaining files in directory 開啟剩餘檔案 - + Shift+F6 - + Delete all *.wav && *.c2 files in SaveDir 刪除所有在SaveDir目錄內 *.wav && *.c2 - + None 不儲存 - + Save all 儲存所有 - + Online User Guide 線上使用者指南 - + Keyboard shortcuts 鍵盤快捷鍵 - + Special mouse commands 滑鼠特殊組合 - + JT9 - + Save decoded 儲存解碼 - + Normal 正常 - + Deep 深度 - + Erase ALL.TXT 刪除 ALL.TXT - + Erase wsjtx_log.adi 刪除通聯日誌 wsjtx_log.adi - + F7 - + Runaway Tx watchdog 運行發射監管計時器 - + JT65 - + JT9+JT65 - + Astronomical data 天文數據 - + List of Type 1 prefixes and suffixes 型態 1 前置碼與後綴清單 - + Settings... 設置... - + Local User Guide 本地使用者指南 - + Open log directory 開啟日誌檔案目錄 - + JT4 - + Message averaging 信息平均值 - + Enable averaging 平均值 - + Enable deep search 開啟深度搜尋 - + WSPR - + Echo Graph 回波圖 - + F8 - + Echo - + EME Echo mode EME 回波模式 - + ISCAT - + Fast Graph 快速圖 - + F9 - + &Download Samples ... 下載樣本(&D) ... - + <html><head/><body><p>Download sample audio files demonstrating the various modes.</p></body></html> <html><head/><body><p>下載演示各種模式的示例音頻檔案.</p></body></html> - + MSK144 - + QRA64 - + Release Notes 發行說明 - + Enable AP for DX Call 開啟 AP 為 DX 呼叫 - + FreqCal - + Measure reference spectrum 測量參考頻譜 - + Measure phase response 測量相位回應 - + Erase reference spectrum 清除參考頻譜 - + Execute frequency calibration cycle 執行頻率校準週期 - + Equalization tools ... 均衡工具 ... - + FT8 - - + + Enable AP 開啟 AP - + Solve for calibration parameters 修正參數的解算 - + Copyright notice 版權聲明 - + Shift+F1 - + Fox log 狐狸日誌 - + FT8 DXpedition Mode User Guide FT8 遠征模式使用者指南 - + Reset Cabrillo log ... 重置卡布里略日誌 ... - + Color highlighting scheme 顏色突出顯示方案 - + Export Cabrillo log ... 匯出卡布里略日誌 ... - + Contest log 競賽日誌 - + Erase WSPR hashtable 擦除 WSPR 哈希表 - + FT4 - + Rig Control Error 無線電設備控制錯誤 - - - + + + Receiving 接收 - + Do you want to reconfigure the radio interface? 是否要重新配置無線電設備接口? - + %1 (%2 sec) audio frames dropped %1 (%2 秒) 音訊幀被丟棄 - + Audio Source 音訊源 - + Reduce system load 降低系統負載 - + Excessive dropped samples - %1 (%2 sec) audio frames dropped in period starting %3 樣品遺失過多 -%1 (%2 sec) 音效的畫面在週期開始時遺失 %3 - + Error Scanning ADIF Log 掃描 ADIF 紀錄錯誤 - + Scanned ADIF log, %1 worked before records created 掃描 ADIF 紀錄紀錄, %1 建立曾經通聯紀錄 - + Error Loading LotW Users Data 載入 LotW 使用者資料錯誤 - + Error Writing WAV File 寫入 WAV 檔案時錯誤 - + Enumerating audio devices 列舉音訊設備 - + Configurations... 設定檔案... - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Message 信息 - + Error Killing jt9.exe Process 錯誤終止 jt9.exe 程序 - + KillByName return code: %1 按結束名稱返回代碼: %1 - + Error removing "%1" 刪除時錯誤 "%1" - + Click OK to retry 單擊 確定 重試 - - + + Improper mode 模式不正確 - - + + File Open Error 檔案開啟錯誤 - - - - - + + + + + Cannot open "%1" for append: %2 無法開啟 "%1" 用於附加: %2 - + Error saving c2 file 保存c2檔案錯誤 - + Error in Sound Input 聲音輸入錯誤 - + Error in Sound Output 聲音輸錯誤 - - - + + + Single-Period Decodes 單週期解碼 - - - + + + Average Decodes 平均解碼 - + Change Operator 變更操作員 - + New operator: 新操作員: - + Status File Error 狀態檔案錯誤 - - + + Cannot open "%1" for writing: %2 無法開啟 "%1" 用於寫入: %2 - + Subprocess Error 子流程錯誤 - + Subprocess failed with exit code %1 子流程失敗, 退出代碼為 %1 - + Running: %1 %2 運行: %1 %2 - + Subprocess error 子進程錯誤 - + Reference spectrum saved 儲存參考頻譜 - + Invalid data in fmt.all at line %1 在 %1 行中 fmt.all 的不合法資料 - + Good Calibration Solution 良好的校準解決方案 - + <pre>%1%L2 ±%L3 ppm %4%L5 ±%L6 Hz @@ -3834,17 +3860,17 @@ list. The list can be maintained in Settings (F2). - + Delete Calibration Measurements 刪除校準測量值 - + The "fmt.all" file will be renamed as "fmt.bak" "fmt.all" 檔案將重新命名為 "fmt.bak" - + If you make fair use of any part of WSJT-X under terms of the GNU General Public License, you must display the following copyright notice prominently in your derivative work: "The algorithms, source code, look-and-feel of WSJT-X and related programs, and protocol specifications for the modes FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 are Copyright (C) 2001-2020 by one or more of the following authors: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; and other members of the WSJT Development Group." @@ -3853,27 +3879,27 @@ list. The list can be maintained in Settings (F2). "WSJT-X 的演演演算法, 原始碼, 外觀和感覺及相關程式, 和協定規格模式 FSK441, FT8, JT4, JT6M, JT9, JT65, JTMS, QRA64, ISCAT, MSK144 的版權 (C) 2001-2019 由以下一個或多個作者: Joseph Taylor, K1JT; Bill Somerville, G4WJS; Steven Franke, K9AN; Nico Palermo, IV3NWV; Greg Beam, KI7MT; Michael Black, W9MDB; Edson Pereira, PY2SDR; Philip Karn, KA9Q; 和 WSJT 開發組的其他成員." - + No data read from disk. Wrong file format? 沒有從磁盤讀取數據. 檔案格式錯誤? - + Confirm Delete 確認刪除 - + Are you sure you want to delete all *.wav and *.c2 files in "%1"? 是否確實要刪除所有 *.wav 和 *.c2 檔案在 "%1"? - + Keyboard Shortcuts 鍵盤快捷鍵 - + <table cellspacing=1> <tr><td><b>Esc </b></td><td>Stop Tx, abort QSO, clear next-call queue</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide (Alt: transmit Tx6)</td></tr> @@ -3967,12 +3993,12 @@ list. The list can be maintained in Settings (F2). </table> - + Special Mouse Commands 特殊滑鼠組合 - + <table cellpadding=5> <tr> <th align="right">Click on</th> @@ -4038,42 +4064,42 @@ list. The list can be maintained in Settings (F2). </table> - + No more files to open. 沒有要打開的檔. - + Spotting to PSK Reporter unavailable 無法發送至PSK Reporter - + Please choose another Tx frequency. WSJT-X will not knowingly transmit another mode in the WSPR sub-band on 30m. 請選擇其他發射頻率. WSJT-X 不會故意傳輸另一個模式在 WSPR 30米子波段上. - + WSPR Guard Band WSPR保護波段 - + Please choose another dial frequency. WSJT-X will not operate in Fox mode in the standard FT8 sub-bands. 請選擇其他頻率. WSJT-X 不會運行狐狸模式在標準 FT8 波段. - + Fox Mode warning 狐狸模式警告 - + Last Tx: %1 最後發射: %1 - + Should you switch to EU VHF Contest mode? To do so, check 'Special operating activity' and @@ -4084,178 +4110,178 @@ To do so, check 'Special operating activity' and 設置高級選項卡上的 '歐洲 VHF 競賽'. - + Should you switch to ARRL Field Day mode? 是否應切換到 ARRL Field Day 模式? - + Should you switch to RTTY contest mode? 是否應切換到 RTTY 競賽模式? - - - - + + + + Add to CALL3.TXT 添加到 CALL3.TXT - + Please enter a valid grid locator 請輸入有效的網格定位 - + Cannot open "%1" for read/write: %2 無法開啟 "%1" 用於讀/寫: %2 - + %1 is already in CALL3.TXT, do you wish to replace it? %1 已經在 CALL3.TXT, 你想替換它嗎? - + Warning: DX Call field is empty. 警告: DX 呼號欄位為空. - + Log file error 日誌檔案錯誤 - + Cannot open "%1" 無法開啟 "%1" - + Error sending log to N1MM 將日誌傳送到 N1MM 時發生錯誤 - + Write returned "%1" 寫入返回 "%1" - + Stations calling DXpedition %1 呼叫遠征電臺 %1 - + Hound 獵犬 - + Tx Messages 發射信息 - - - + + + Confirm Erase 確認擦除 - + Are you sure you want to erase file ALL.TXT? 是否確實要擦除 ALL.Txt 檔案? - - + + Confirm Reset 確認重置 - + Are you sure you want to erase your contest log? 是否確實要擦除競賽日誌? - + Doing this will remove all QSO records for the current contest. They will be kept in the ADIF log file but will not be available for export in your Cabrillo log. 執行此動作將移除目前競賽的所有通聯記錄. 它們將保留在 ADIF 日誌檔案中, 但無法匯出到您的卡布里略日誌中. - + Cabrillo Log saved 卡布里略日誌已儲存 - + Are you sure you want to erase file wsjtx_log.adi? 是否確實要擦除 wsjtx_log.adi 檔案? - + Are you sure you want to erase the WSPR hashtable? 是否確定要擦除 WSPR 哈希表? - + Tune digital gain 調諧數碼增益 - + Transmit digital gain 傳輸數碼增益 - + Prefixes 前綴 - + Network Error 網路錯誤 - + Error: %1 UDP server %2:%3 錯誤: %1 UDP 服務器 %2:%3 - + File Error 檔案錯誤 - + Phase Training Disabled 關閉階段訓練 - + Phase Training Enabled 開啟階段訓練 - + WD:%1m - - + + Log File Error 日誌檔案錯誤 - + Are you sure you want to clear the QSO queues? 是否要清除通聯佇列? @@ -4598,22 +4624,21 @@ Error(%2): %3 SoundInput - + An error opening the audio input device has occurred. 開啟音頻輸入設備時錯誤. - + An error occurred during read from the audio input device. 從音頻輸入設備讀取時錯誤. - Audio data not being fed to the audio input device fast enough. - 音頻數據沒有足夠提供饋送到音頻輸入設備. + 音頻數據沒有足夠提供饋送到音頻輸入設備. - + Non-recoverable error, audio input device not usable at this time. 不可恢復的錯誤, 音頻輸入設備此時不可用. @@ -4628,37 +4653,37 @@ Error(%2): %3 設備不支持請求輸入的音頻格式. - + Failed to initialize audio sink device 無法初始化音頻接收器設備 - + Idle 閑置 - + Receiving 接收 - + Suspended 暫停 - + Interrupted 中斷 - + Error 錯誤 - + Stopped 停止 @@ -4666,67 +4691,67 @@ Error(%2): %3 SoundOutput - + An error opening the audio output device has occurred. 開啟音頻輸出設備時錯誤. - + An error occurred during write to the audio output device. 寫入音頻輸出設備期間錯誤. - + Audio data not being fed to the audio output device fast enough. 音頻數據未以足夠快的速度饋送到音頻輸出設備. - + Non-recoverable error, audio output device not usable at this time. 不可恢復錯誤, 音頻輸出設備此時不可用. - + Requested output audio format is not valid. 請求的輸出音頻格式無效. - + Requested output audio format is not supported on device. 設備不支持請求輸出的音頻格式. - + No audio output device configured. 未設定音訊輸出裝置. - + Idle 閑置 - + Sending 發送 - + Suspended 暫停 - + Interrupted 中斷 - + Error 錯誤 - + Stopped 停止 @@ -4734,22 +4759,22 @@ Error(%2): %3 StationDialog - + Add Station 添加電臺 - + &Band: 波段(&B): - + &Offset (MHz): 偏移 (M&Hz): - + &Antenna: 天線(&A): @@ -5715,7 +5740,7 @@ radio interface behave as expected. 音效卡 - + Select the audio CODEC to use for transmitting. If this is your default device for system sounds then ensure that all system sounds are disabled otherwise @@ -5733,46 +5758,46 @@ transmitting periods. 自上次上傳以來的天數 - + Select the audio CODEC to use for receiving. 選擇要用於接收的音頻信號. - + &Input: 輸入(&I): - + Select the channel to use for receiving. 選擇要用於接收的通道. - - + + Mono 單聲道 - - + + Left 左聲道 - - + + Right 右聲道 - - + + Both 雙聲道 - + Select the audio channel used for transmission. Unless you have multiple radios connected on different channels; then you will usually want to select mono or @@ -5788,7 +5813,17 @@ both here. 啟用甚高頻和子模式功能 - + + Data Bits + + + + + Stop Bits + + + + Ou&tput: 輸出(&t): @@ -6033,67 +6068,67 @@ and DX Grid fields when a 73 or free text message is sent. <html><head/><body><p>輸入 WSJT-X 應向其發送更新的 UDP 伺服器的服務埠號. 如果為零, 將不會廣播任何更新.</p></body></html> - + <html><head/><body><p>With this enabled WSJT-X will accept certain requests back from a UDP server that receives decode messages.</p></body></html> <html><head/><body><p>啟用此功能後,WSJT-X 將接受來自接收解碼消息的 UDP 伺服器的某些請求.</p></body></html> - + Accept UDP requests 接受UDP請求 - + <html><head/><body><p>Indicate acceptance of an incoming UDP request. The effect of this option varies depending on the operating system and window manager, its intent is to notify the acceptance of an incoming UDP request even if this application is minimized or hidden.</p></body></html> <html><head/><body><p>指示接受傳入的 UDP 請求.此選項的效果因操作系統和窗口管理器而異,其目的是通知接受傳入的 UDP 請求,即使此應用程序最小化或隱藏</p></body></html> - + Notify on accepted UDP request 在接受UDP的請求時通知 - + <html><head/><body><p>Restore the window from minimized if an UDP request is accepted.</p></body></html> <html><head/><body><p>如果接受 UDP 請求,則從最小化還原窗口.</p></body></html> - + Accepted UDP request restores window 接受UDP請求還原窗口 - + Secondary UDP Server (deprecated) 輔助UDP 伺服器 (已棄用) - + <html><head/><body><p>When checked, WSJT-X will broadcast a logged contact in ADIF format to the configured hostname and port. </p></body></html> <html><head/><body><p>選擇後, WSJT-X 將以 ADIF 格式將記錄的聯絡廣播到設定的主機名稱和埠. </p></body></html> - + Enable logged contact ADIF broadcast 開啟記錄連絡 ADIF 廣播 - + Server name or IP address: 伺服器名稱或 IP 位址: - + <html><head/><body><p>Optional host name of N1MM Logger+ program to receive ADIF UDP broadcasts. This is usually 'localhost' or ip address 127.0.0.1</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable broadcasting of ADIF information via UDP.</p></body></html> <html><head/><body><p>N1MM Logger+ 程式可選電腦主機用於接收 ADIF UDP 廣播. 這通常是 'localhost' 或 IP 地址 127.0.0.1</p><p>格式:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">主機名稱</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 地址</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 地址</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 多播組地址</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 多播組地址</li></ul><p>清除此欄位將停用透過UDP廣播ADIF資訊.</p></body></html> - + Server port number: 伺服器連接埠號: - + <html><head/><body><p>Enter the port number that WSJT-X should use for UDP broadcasts of ADIF log information. For N1MM Logger+, this value should be 2333. If this is zero, no updates will be broadcast.</p></body></html> <html><head/><body><p>輸入 WSJT-X 應用於 ADIF 日誌資訊的 UDP 廣播的埠號. 對於 N1MM Logger+, 此值應為 2333. 如果為零, 將不會廣播任何更新.</p></body></html> @@ -6537,63 +6572,63 @@ Right click for insert and delete options. main - + Another instance may be running 另一個應用程式可能正在執行 - + try to remove stale lock file? 嘗試刪除陳舊的鎖檔? - + Failed to create a temporary directory 無法建立暫存目錄 - - + + Path: "%1" 目錄: "%1" - + Failed to create a usable temporary directory 無法建立可用的暫存目錄 - + Another application may be locking the directory 另一個應用程式可能正在鎖定目錄 - + Failed to create data directory 無法建立資料目錄 - + path: "%1" 目錄: "%1" - + Shared memory error 共用記憶體錯誤 - + Unable to create shared memory segment 無法建立共用記憶體段 - + Sub-process error 子進程錯誤 - + Failed to close orphaned jt9 process 無法關閉遺留的jt9進程 From 662ed0fa7a0feeda2e91e2c5e1d6bd843ad65cca Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 2 Nov 2020 15:33:44 +0000 Subject: [PATCH 53/73] Network interface selection for outgoing UDP multicast datagrams Default selection is the loop-back interface. Users who require interoperation between WSJT-X instances cooperating applications running on different hosts should select a suitable network interface and carefully choose a multicast group address, and TTL, that has minimal scope covering the necessary network(s). Using 224.0.0.1 is a reasonable strategy if all hosts are on the same subnet. Administratively scoped multicast group addresses like those within 239.255.0.0/16 can cover larger boundaries, but care must be taken if the local subnet has access to a multicast enabled router. The IPv4 broadcast address (255.255.255.255) may be used as an alternative to multicast UDP, but note that WSJT-X will only send broadcast UDP datagrams on the loop-back interface, so all recipient applications must be running on the same host system. The reference UDP Message protocol applications are being extended to be configurable with a list of interfaces to join a multicast group address on. By default they will only join on the loop-back interface, which is also recommended for any applications designed to take part in the WSJT-X UDP Message Protocol. This allows full user control of the scope of multicast group membership with a very conservative default mode that will work with all interoperating applications running on the same host system. --- Configuration.cpp | 159 +++++++++++++++++++++++++++- Configuration.hpp | 6 +- Configuration.ui | 61 ++++++++--- Network/MessageClient.cpp | 193 ++++++++++++++++++++++++---------- Network/MessageClient.hpp | 15 ++- UDPExamples/MessageServer.cpp | 85 +++++++-------- UDPExamples/MessageServer.hpp | 7 +- UDPExamples/UDPDaemon.cpp | 19 +++- qt_helpers.hpp | 26 +++++ tests/test_qt_helpers.cpp | 74 +++++++++++++ widgets/mainwindow.cpp | 4 +- 11 files changed, 510 insertions(+), 139 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index f244ecd9f..fac5564ab 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -163,6 +163,9 @@ #include #include #include +#include +#include +#include #include #include "pimpl_impl.hpp" @@ -439,6 +442,10 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); + void load_network_interfaces (QComboBox *, QString const& current); + Q_SLOT void host_info_results (QHostInfo); + void check_multicast (QHostAddress const&); + void find_tab (QWidget *); void initialize_models (); @@ -492,6 +499,8 @@ private: Q_SLOT void on_add_macro_line_edit_editingFinished (); Q_SLOT void delete_macro (); void delete_selected_macros (QModelIndexList); + Q_SLOT void on_udp_server_line_edit_textChanged (QString const&); + Q_SLOT void on_udp_server_line_edit_editingFinished (); Q_SLOT void on_save_path_select_push_button_clicked (bool); Q_SLOT void on_azel_path_select_push_button_clicked (bool); Q_SLOT void on_calibration_intercept_spin_box_valueChanged (double); @@ -641,7 +650,11 @@ private: bool use_dynamic_grid_; QString opCall_; QString udp_server_name_; + bool udp_server_name_edited_; + int dns_lookup_id_; port_type udp_server_port_; + QString udp_interface_name_; + int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; bool broadcast_to_n1mm_; @@ -741,6 +754,8 @@ QString Configuration::opCall() const {return m_->opCall_;} void Configuration::opCall (QString const& call) {m_->opCall_ = call;} QString Configuration::udp_server_name () const {return m_->udp_server_name_;} auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;} +QString Configuration::udp_interface_name () const {return m_->udp_interface_name_;} +int Configuration::udp_TTL () const {return m_->udp_TTL_;} bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;} QString Configuration::n1mm_server_name () const {return m_->n1mm_server_name_;} auto Configuration::n1mm_server_port () const -> port_type {return m_->n1mm_server_port_;} @@ -995,6 +1010,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network , transceiver_command_number_ {0} , degrade_ {0.} // initialize to zero each run, not // saved in settings + , udp_server_name_edited_ {false} + , dns_lookup_id_ {-1} { ui_->setupUi (this); @@ -1044,6 +1061,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network // this must be done after the default paths above are set read_settings (); + // set up dynamic loading of audio devices connect (ui_->sound_input_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor}); load_audio_devices (QAudio::AudioInput, ui_->sound_input_combo_box, &next_audio_input_device_); @@ -1059,6 +1077,13 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network QGuiApplication::restoreOverrideCursor (); }); + // set up dynamic loading of network interfaces + connect (ui_->udp_interface_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { + QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor}); + load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); + QGuiApplication::restoreOverrideCursor (); + }); + // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { ui_->LotW_CSV_fetch_push_button->setEnabled (true); @@ -1335,7 +1360,14 @@ void Configuration::impl::initialize_models () ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval); ui_->opCallEntry->setText (opCall_); ui_->udp_server_line_edit->setText (udp_server_name_); + on_udp_server_line_edit_editingFinished (); ui_->udp_server_port_spin_box->setValue (udp_server_port_); + load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); + if (!udp_interface_name_.size ()) + { + udp_interface_name_ = ui_->udp_interface_combo_box->currentData ().toString (); + } + ui_->udp_TTL_spin_box->setValue (udp_TTL_); ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_); ui_->n1mm_server_name_line_edit->setText (n1mm_server_name_); ui_->n1mm_server_port_spin_box->setValue (n1mm_server_port_); @@ -1513,6 +1545,8 @@ void Configuration::impl::read_settings () rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value (); opCall_ = settings_->value ("OpCall", "").toString (); udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString (); + udp_interface_name_ = settings_->value ("UDPInterface").toString (); + udp_TTL_ = settings_->value ("UDPTTL").toInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString (); n1mm_server_port_ = settings_->value ("N1MMServerPort", 2333).toUInt (); @@ -1641,6 +1675,8 @@ void Configuration::impl::write_settings () settings_->setValue ("OpCall", opCall_); settings_->setValue ("UDPServer", udp_server_name_); settings_->setValue ("UDPServerPort", udp_server_port_); + settings_->setValue ("UDPInterface", udp_interface_name_); + settings_->setValue ("UDPTTL", udp_TTL_); settings_->setValue ("N1MMServer", n1mm_server_name_); settings_->setValue ("N1MMServerPort", n1mm_server_port_); settings_->setValue ("BroadcastToN1MM", broadcast_to_n1mm_); @@ -1843,6 +1879,12 @@ bool Configuration::impl::validate () return false; } + if (dns_lookup_id_ > -1) + { + MessageBox::information_message (this, tr ("Pending DNS lookup, please try again later")); + return false; + } + return true; } @@ -2061,20 +2103,30 @@ void Configuration::impl::accept () pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked (); pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked (); opCall_=ui_->opCallEntry->text(); - auto new_server = ui_->udp_server_line_edit->text (); - if (new_server != udp_server_name_) + + auto new_server = ui_->udp_server_line_edit->text ().trimmed (); + auto new_interface = ui_->udp_interface_combo_box->currentData ().toString (); + if (new_server != udp_server_name_ || new_interface != udp_interface_name_) { udp_server_name_ = new_server; - Q_EMIT self_->udp_server_changed (new_server); + udp_interface_name_ = new_interface; + Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_name_); } auto new_port = ui_->udp_server_port_spin_box->value (); if (new_port != udp_server_port_) { udp_server_port_ = new_port; - Q_EMIT self_->udp_server_port_changed (new_port); + Q_EMIT self_->udp_server_port_changed (udp_server_port_); } - + + auto new_TTL = ui_->udp_TTL_spin_box->value (); + if (new_TTL != udp_TTL_) + { + udp_TTL_ = new_TTL; + Q_EMIT self_->udp_TTL_changed (udp_TTL_); + } + if (ui_->accept_udp_requests_check_box->isChecked () != accept_udp_requests_) { accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked (); @@ -2130,6 +2182,12 @@ void Configuration::impl::accept () void Configuration::impl::reject () { + if (dns_lookup_id_ > -1) + { + QHostInfo::abortHostLookup (dns_lookup_id_); + dns_lookup_id_ = -1; + } + initialize_models (); // reverts to settings as at exec () // check if the Transceiver instance changed, in which case we need @@ -2344,6 +2402,72 @@ void Configuration::impl::on_add_macro_push_button_clicked (bool /* checked */) } } +void Configuration::impl::on_udp_server_line_edit_textChanged (QString const&) +{ + udp_server_name_edited_ = true; +} + +void Configuration::impl::on_udp_server_line_edit_editingFinished () +{ + if (udp_server_name_edited_) + { + auto const& server = ui_->udp_server_line_edit->text ().trimmed (); + QHostAddress ha {server}; + if (server.size () && ha.isNull ()) + { + // queue a host address lookup + qDebug () << "server host DNS lookup:" << server; +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + dns_lookup_id_ = QHostInfo::lookupHost (server, this, &Configuration::impl::host_info_results); +#else + dns_lookup_id_ = QHostInfo::lookupHost (server, this, SLOT (host_info_results (QHostInfo))); +#endif + } + else + { + check_multicast (ha); + } + } +} + +void Configuration::impl::host_info_results (QHostInfo host_info) +{ + if (host_info.lookupId () != dns_lookup_id_) return; + dns_lookup_id_ = -1; + if (QHostInfo::NoError != host_info.error ()) + { + MessageBox::critical_message (this, tr ("UDP server DNS lookup failed"), host_info.errorString ()); + } + else + { + auto const& server_addresses = host_info.addresses (); + qDebug () << "message server addresses:" << server_addresses; + if (server_addresses.size ()) + { + check_multicast (server_addresses[0]); + } + } +} + +void Configuration::impl::check_multicast (QHostAddress const& ha) +{ + auto is_multicast = is_multicast_address (ha); + ui_->udp_interface_label->setVisible (is_multicast); + ui_->udp_interface_combo_box->setVisible (is_multicast); + ui_->udp_TTL_label->setVisible (is_multicast); + ui_->udp_TTL_spin_box->setVisible (is_multicast); + if (isVisible ()) + { + if (is_MAC_ambiguous_multicast_address (ha)) + { + MessageBox::warning_message (this, tr ("MAC-ambiguous multicast groups addresses not supported")); + find_tab (ui_->udp_server_line_edit); + ui_->udp_server_line_edit->clear (); + } + } + udp_server_name_edited_ = false; +} + void Configuration::impl::delete_frequencies () { auto selection_model = ui_->frequencies_table_view->selectionModel (); @@ -2868,6 +2992,31 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com combo_box->setCurrentIndex (current_index); } +// load the available network interfaces into the selection combo box +void Configuration::impl::load_network_interfaces (QComboBox * combo_box, QString const& current) +{ + combo_box->clear (); + int current_index = -1; + for (auto const& interface : QNetworkInterface::allInterfaces ()) + { + if (interface.flags () & QNetworkInterface::IsUp) + { + auto const& name = interface.name (); + combo_box->addItem (interface.humanReadableName (), name); + // select the first loopback interface as a default to + // discourage spamming the network (possibly the Internet), + // particularly important with administratively scoped + // multicast UDP + if (name == current + || (!current.size () && (interface.flags () & QNetworkInterface::IsLoopBack))) + { + current_index = combo_box->count () - 1; + } + } + } + combo_box->setCurrentIndex (current_index); +} + // enable only the channels that are supported by the selected audio device void Configuration::impl::update_audio_channels (QComboBox const * source_combo_box, int index, QComboBox * combo_box, bool allow_both) { diff --git a/Configuration.hpp b/Configuration.hpp index 8594a4a6f..403673663 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -21,7 +21,6 @@ class Bands; class FrequencyList_v2; class StationList; class QStringListModel; -class QHostAddress; class LotWUsers; class DecodeHighlightingModel; class LogBook; @@ -152,6 +151,8 @@ public: void opCall (QString const&); QString udp_server_name () const; port_type udp_server_port () const; + QString udp_interface_name () const; + int udp_TTL () const; QString n1mm_server_name () const; port_type n1mm_server_port () const; bool valid_n1mm_info () const; @@ -273,8 +274,9 @@ public: // // This signal is emitted when the UDP server changes // - Q_SIGNAL void udp_server_changed (QString const& udp_server) const; + Q_SIGNAL void udp_server_changed (QString& udp_server_name, QString const& network_interface) const; Q_SIGNAL void udp_server_port_changed (port_type server_port) const; + Q_SIGNAL void udp_TTL_changed (int TTL) const; Q_SIGNAL void accept_udp_requests_changed (bool checked) const; // signal updates to decode highlighting diff --git a/Configuration.ui b/Configuration.ui index fbd53c422..fd8fb8955 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -7,7 +7,7 @@ 0 0 554 - 556 + 560 @@ -1864,12 +1864,6 @@ and DX Grid fields when a 73 or free text message is sent. - - - 0 - 0 - - <html><head/><body><p>Optional hostname of network service to receive decodes.</p><p>Formats:</p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">hostname</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv4 multicast group address</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">IPv6 multicast group address</li></ul><p>Clearing this field will disable the broadcasting of UDP status updates.</p></body></html> @@ -1898,6 +1892,39 @@ and DX Grid fields when a 73 or free text message is sent. + + + + Outgoing interface: + + + udp_interface_combo_box + + + + + + + + + + 255 + + + 1 + + + + + + + Multicast TTL: + + + udp_TTL_spin_box + + +
@@ -3084,6 +3111,8 @@ Right click for insert and delete options. psk_reporter_tcpip_check_box udp_server_line_edit udp_server_port_spin_box + udp_interface_combo_box + udp_TTL_spin_box accept_udp_requests_check_box udpWindowToFront udpWindowRestore @@ -3101,8 +3130,8 @@ Right click for insert and delete options. include_WAE_check_box rescan_log_push_button LotW_CSV_URL_line_edit - LotW_days_since_upload_spin_box LotW_CSV_fetch_push_button + LotW_days_since_upload_spin_box sbNtrials sbAggressive cbTwoPass @@ -3118,11 +3147,11 @@ Right click for insert and delete options. rbHound rbNA_VHF_Contest rbField_Day - Field_Day_Exchange rbEU_VHF_Contest rbRTTY_Roundup - RTTY_Exchange rbWW_DIGI + Field_Day_Exchange + RTTY_Exchange @@ -3192,13 +3221,13 @@ Right click for insert and delete options. - - - - - - + + + + + + diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 3c208fd3f..57ffb2806 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -6,16 +6,16 @@ #include #include +#include #include #include #include #include -#include #include #include #include "NetworkMessage.hpp" - +#include "qt_helpers.hpp" #include "pimpl_impl.hpp" #include "moc_MessageClient.cpp" @@ -34,14 +34,15 @@ class MessageClient::impl public: impl (QString const& id, QString const& version, QString const& revision, - port_type server_port, MessageClient * self) + port_type server_port, int TTL, MessageClient * self) : self_ {self} - , dns_lookup_id_ {0} , enabled_ {false} , id_ {id} , version_ {version} , revision_ {revision} + , dns_lookup_id_ {-1} , server_port_ {server_port} + , TTL_ {TTL} , schema_ {2} // use 2 prior to negotiation not 1 which is broken , heartbeat_timer_ {new QTimer {this}} { @@ -49,9 +50,6 @@ public: connect (this, &QIODevice::readyRead, this, &impl::pending_datagrams); heartbeat_timer_->start (NetworkMessage::pulse * 1000); - - // bind to an ephemeral port - bind (); } ~impl () @@ -61,7 +59,10 @@ public: enum StreamStatus {Fail, Short, OK}; - void parse_message (QByteArray const& msg); + void set_server (QString const& server_name, QString const& network_interface_name); + Q_SLOT void host_info_results (QHostInfo); + void start (); + void parse_message (QByteArray const&); void pending_datagrams (); void heartbeat (); void closedown (); @@ -69,27 +70,26 @@ public: void send_message (QByteArray const&); void send_message (QDataStream const& out, QByteArray const& message) { - if (OK == check_status (out)) - { - send_message (message); - } - else - { - Q_EMIT self_->error ("Error creating UDP message"); - } + if (OK == check_status (out)) + { + send_message (message); + } + else + { + Q_EMIT self_->error ("Error creating UDP message"); + } } - Q_SLOT void host_info_results (QHostInfo); - MessageClient * self_; - int dns_lookup_id_; bool enabled_; QString id_; QString version_; QString revision_; - QString server_string_; - port_type server_port_; + int dns_lookup_id_; QHostAddress server_; + port_type server_port_; + int TTL_; + QNetworkInterface network_interface_; quint32 schema_; QTimer * heartbeat_timer_; std::vector blocked_addresses_; @@ -101,37 +101,117 @@ public: #include "MessageClient.moc" +void MessageClient::impl::set_server (QString const& server_name, QString const& network_interface_name) +{ + server_.setAddress (server_name); + network_interface_ = QNetworkInterface::interfaceFromName (network_interface_name); + if (server_.isNull () && server_name.size ()) // DNS lookup required + { + // queue a host address lookup +#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) + dns_lookup_id_ = QHostInfo::lookupHost (server_name, this, &MessageClient::impl::host_info_results); +#else + dns_lookup_id_ = QHostInfo::lookupHost (server_name, this, SLOT (host_info_results (QHostInfo))); +#endif + } + else + { + start (); + } +} + void MessageClient::impl::host_info_results (QHostInfo host_info) { if (host_info.lookupId () != dns_lookup_id_) return; + dns_lookup_id_ = -1; if (QHostInfo::NoError != host_info.error ()) { - Q_EMIT self_->error ("UDP server lookup failed:\n" + host_info.errorString ()); - pending_messages_.clear (); // discard + Q_EMIT self_->error ("UDP server DNS lookup failed: " + host_info.errorString ()); } - else if (host_info.addresses ().size ()) + else { - auto server = host_info.addresses ()[0]; - if (blocked_addresses_.end () == std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server)) + auto const& server_addresses = host_info.addresses (); + if (server_addresses.size ()) { - server_ = server; - TRACE_UDP ("resulting server:" << server); + server_ = server_addresses[0]; + } + } + start (); +} - // send initial heartbeat which allows schema negotiation - heartbeat (); +void MessageClient::impl::start () +{ + if (server_.isNull ()) + { + Q_EMIT self_->close (); + pending_messages_.clear (); // discard + return; + } - // clear any backlog - while (pending_messages_.size ()) + if (blocked_addresses_.end () != std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server_)) + { + Q_EMIT self_->error ("UDP server blocked, please try another"); + pending_messages_.clear (); // discard + return; + } + + TRACE_UDP ("Trying server:" << server_.toString () << "on interface:" << network_interface_.humanReadableName ()); + QHostAddress interface_ip {QHostAddress::Any}; + if (network_interface_.isValid ()) + { + if (is_multicast_address (server_) && !(network_interface_.flags () & QNetworkInterface::CanMulticast)) + { + Q_EMIT self_->error ("Network interface is not multicast capable, please try another"); + return; + } + for (auto const& ae : network_interface_.addressEntries ()) + { + auto const& ip = ae.ip (); + if (server_.protocol () == ip.protocol ()) { - send_message (pending_messages_.dequeue ()); + interface_ip = ip; + break; } } - else + if (QHostAddress {QHostAddress::Any} == interface_ip) { - Q_EMIT self_->error ("UDP server blocked, please try another"); + Q_EMIT self_->error ("Network interface has no suitable address for server IP protocol, please try another"); pending_messages_.clear (); // discard + return; } } + + if (server_.isBroadcast ()) + { + // only allow broadcast on the loopback interface to avoid + // flooding the local subnet which may be large with some ISPs + //interface_ip.setAddress ("127.0.0.1"); + } + + if (localAddress () != interface_ip) + { + if (UnconnectedState != state () || state ()) + { + close (); + } + // bind to an ephemeral port on the selected interface and set + // up for sending datagrams + bind (interface_ip); + setMulticastInterface (network_interface_); + + // set multicast TTL to limit scope when sending to multicast + // group addresses + setSocketOption (MulticastTtlOption, TTL_); + } + + // send initial heartbeat which allows schema negotiation + heartbeat (); + + // clear any backlog + while (pending_messages_.size ()) + { + send_message (pending_messages_.dequeue ()); + } } void MessageClient::impl::pending_datagrams () @@ -428,9 +508,11 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre } MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision, - QString const& server, port_type server_port, QObject * self) + QString const& server_name, port_type server_port, + QString const& network_interface_name, + int TTL, QObject * self) : QObject {self} - , m_ {id, version, revision, server_port, this} + , m_ {id, version, revision, server_port, TTL, this} { connect (&*m_ #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) @@ -449,8 +531,8 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString #endif Q_EMIT error (m_->errorString ()); } - }); - set_server (server); + }); + m_->set_server (server_name, network_interface_name); } QHostAddress MessageClient::server_address () const @@ -463,20 +545,9 @@ auto MessageClient::server_port () const -> port_type return m_->server_port_; } -void MessageClient::set_server (QString const& server) +void MessageClient::set_server (QString const& server_name, QString const& network_interface_name) { - m_->server_.clear (); - m_->server_string_ = server; - if (server.size ()) - { - // queue a host address lookup - TRACE_UDP ("server host DNS lookup:" << server); -#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) - m_->dns_lookup_id_ = QHostInfo::lookupHost (server, &*m_, &MessageClient::impl::host_info_results); -#else - m_->dns_lookup_id_ = QHostInfo::lookupHost (server, &*m_, SLOT (host_info_results (QHostInfo))); -#endif - } + m_->set_server (server_name, network_interface_name); } void MessageClient::set_server_port (port_type server_port) @@ -484,6 +555,12 @@ void MessageClient::set_server_port (port_type server_port) m_->server_port_ = server_port; } +void MessageClient::set_TTL (int TTL) +{ + m_->TTL_ = TTL; + m_->setSocketOption (QAbstractSocket::MulticastTtlOption, m_->TTL_); +} + void MessageClient::enable (bool flag) { m_->enabled_ = flag; @@ -499,7 +576,7 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Status, m_->id_, m_->schema_}; @@ -516,7 +593,7 @@ void MessageClient::decode (bool is_new, QTime time, qint32 snr, float delta_tim , QString const& mode, QString const& message_text, bool low_confidence , bool off_air) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Decode, m_->id_, m_->schema_}; @@ -531,7 +608,7 @@ void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delt , qint32 drift, QString const& callsign, QString const& grid, qint32 power , bool off_air) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::WSPRDecode, m_->id_, m_->schema_}; @@ -544,7 +621,7 @@ void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delt void MessageClient::decodes_cleared () { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Clear, m_->id_, m_->schema_}; @@ -561,7 +638,7 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr , QString const& my_grid, QString const& exchange_sent , QString const& exchange_rcvd, QString const& propmode) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_, m_->schema_}; @@ -576,7 +653,7 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr void MessageClient::logged_ADIF (QByteArray const& ADIF_record) { - if (m_->server_port_ && !m_->server_string_.isEmpty ()) + if (m_->server_port_ && !m_->server_.isNull ()) { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::LoggedADIF, m_->id_, m_->schema_}; diff --git a/Network/MessageClient.hpp b/Network/MessageClient.hpp index afe361fab..d0066dbe4 100644 --- a/Network/MessageClient.hpp +++ b/Network/MessageClient.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "Radio.hpp" #include "pimpl_h.hpp" @@ -34,19 +35,25 @@ public: // // messages will be silently dropped until a server host lookup is complete MessageClient (QString const& id, QString const& version, QString const& revision, - QString const& server, port_type server_port, QObject * parent = nullptr); + QString const& server_name, port_type server_port, + QString const& network_interface_name, + int TTL, QObject * parent = nullptr); // query server details QHostAddress server_address () const; port_type server_port () const; - // initiate a new server host lookup or is the server name is empty - // the sending of messages is disabled - Q_SLOT void set_server (QString const& server = QString {}); + // initiate a new server host lookup or if the server name is empty + // the sending of messages is disabled, if an interface is specified + // then that interface is used for outgoing datagrams + Q_SLOT void set_server (QString const& server_name, QString const& network_interface_name); // change the server port messages are sent to Q_SLOT void set_server_port (port_type server_port = 0u); + // change the server port messages are sent to + Q_SLOT void set_TTL (int TTL); + // enable incoming messages Q_SLOT void enable (bool); diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 42a9689ef..fc36aad9d 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -32,7 +32,6 @@ public: : self_ {self} , version_ {version} , revision_ {revision} - , port_ {0u} , clock_ {new QTimer {this}} { // register the required types with Qt @@ -78,8 +77,8 @@ public: MessageServer * self_; QString version_; QString revision_; - port_type port_; QHostAddress multicast_group_address_; + QStringList network_interfaces_; static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint; struct Client { @@ -109,56 +108,39 @@ MessageServer::impl::BindMode constexpr MessageServer::impl::bind_mode_; void MessageServer::impl::leave_multicast_group () { - if (!multicast_group_address_.isNull () && BoundState == state () -#if QT_VERSION >= 0x050600 - && multicast_group_address_.isMulticast () -#endif - ) + if (BoundState == state () && is_multicast_address (multicast_group_address_)) { - for (auto const& interface : QNetworkInterface::allInterfaces ()) + for (auto const& if_name : network_interfaces_) { - if (QNetworkInterface::CanMulticast & interface.flags ()) - { - leaveMulticastGroup (multicast_group_address_, interface); - } + leaveMulticastGroup (multicast_group_address_, QNetworkInterface::interfaceFromName (if_name)); } } } void MessageServer::impl::join_multicast_group () { - if (BoundState == state () - && !multicast_group_address_.isNull () -#if QT_VERSION >= 0x050600 - && multicast_group_address_.isMulticast () -#endif - ) + if (BoundState == state () && is_multicast_address (multicast_group_address_)) { - auto mcast_iface = multicastInterface (); - if (IPv4Protocol == multicast_group_address_.protocol () - && IPv4Protocol != localAddress ().protocol ()) + if (network_interfaces_.size ()) { - close (); - bind (QHostAddress::AnyIPv4, port_, bind_mode_); - } - bool joined {false}; - for (auto const& interface : QNetworkInterface::allInterfaces ()) - { - if (QNetworkInterface::CanMulticast & interface.flags ()) + for (auto const& if_name : network_interfaces_) { - // Windows requires outgoing interface to match - // interface to be joined while joining, at least for - // IPv4 it seems to - setMulticastInterface (interface); - - joined |= joinMulticastGroup (multicast_group_address_, interface); + joinMulticastGroup (multicast_group_address_, QNetworkInterface::interfaceFromName (if_name)); } } - if (!joined) + else { - multicast_group_address_.clear (); + // find the loop-back interface and join on that + for (auto const& net_if : QNetworkInterface::allInterfaces ()) + { + auto flags = QNetworkInterface::IsUp | QNetworkInterface::IsLoopBack | QNetworkInterface::CanMulticast; + if ((net_if.flags () & flags) == flags) + { + joinMulticastGroup (multicast_group_address_, net_if); + break; + } + } } - setMulticastInterface (mcast_iface); } } @@ -448,27 +430,34 @@ MessageServer::MessageServer (QObject * parent, QString const& version, QString { } -void MessageServer::start (port_type port, QHostAddress const& multicast_group_address) +void MessageServer::start (port_type port, QHostAddress const& multicast_group_address + , QStringList const& network_interface_names) { - if (port != m_->port_ - || multicast_group_address != m_->multicast_group_address_) + if (port != m_->localPort () || multicast_group_address != m_->multicast_group_address_) { m_->leave_multicast_group (); - if (impl::BoundState == m_->state ()) + if (impl::UnconnectedState != m_->state ()) { m_->close (); } - m_->multicast_group_address_ = multicast_group_address; - auto address = m_->multicast_group_address_.isNull () - || impl::IPv4Protocol != m_->multicast_group_address_.protocol () ? QHostAddress::Any : QHostAddress::AnyIPv4; - if (port && m_->bind (address, port, m_->bind_mode_)) + if (!(multicast_group_address.isNull () || is_multicast_address (multicast_group_address))) { - m_->port_ = port; - m_->join_multicast_group (); + Q_EMIT error ("Invalid multicast group address"); + } + else if (is_MAC_ambiguous_multicast_address (multicast_group_address)) + { + Q_EMIT error ("MAC-ambiguous IPv4 multicast group address not supported"); } else { - m_->port_ = 0; + m_->multicast_group_address_ = multicast_group_address; + m_->network_interfaces_ = network_interface_names; + QHostAddress local_addr {is_multicast_address (multicast_group_address) + && impl::IPv4Protocol == multicast_group_address.protocol () ? QHostAddress::AnyIPv4 : QHostAddress::Any}; + if (port && m_->bind (local_addr, port, m_->bind_mode_)) + { + m_->join_multicast_group (); + } } } } diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 184410117..449c70f4b 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -2,6 +2,8 @@ #define MESSAGE_SERVER_HPP__ #include +#include +#include #include #include #include @@ -38,8 +40,9 @@ public: // start or restart the server, if the multicast_group_address // argument is given it is assumed to be a multicast group address // which the server will join - Q_SLOT void start (port_type port, - QHostAddress const& multicast_group_address = QHostAddress {}); + Q_SLOT void start (port_type port + , QHostAddress const& multicast_group_address = QHostAddress {} + , QStringList const& network_interface_names = QStringList {}); // ask the client to clear one or both of the decode windows Q_SLOT void clear_decodes (QString const& id, quint8 window = 0); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index be1b5edeb..2668a6021 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -20,6 +20,9 @@ #include #include +#include +#include +#include #include #include #include @@ -144,7 +147,7 @@ class Server Q_OBJECT public: - Server (port_type port, QHostAddress const& multicast_group) + Server (port_type port, QHostAddress const& multicast_group, QStringList const& network_interface_names) : server_ {new MessageServer {this}} { // connect up server @@ -154,7 +157,7 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); - server_->start (port, multicast_group); + server_->start (port, multicast_group, network_interface_names); } private: @@ -232,9 +235,19 @@ int main (int argc, char * argv[]) app.translate ("UDPDaemon", "GROUP")); parser.addOption (multicast_addr_option); + QCommandLineOption network_interface_option (QStringList {"i", "network-interface"}, + app.translate ("UDPDaemon", + "Where is the network interface name to join on.\n" + "This option can be passed more than once to specify multiple network interfaces\n" + "The default is use just the loop back interface."), + app.translate ("UDPDaemon", "INTERFACE")); + parser.addOption (network_interface_option); + parser.process (app); - Server server {static_cast (parser.value (port_option).toUInt ()), QHostAddress {parser.value (multicast_addr_option)}}; + Server server {static_cast (parser.value (port_option).toUInt ()) + , QHostAddress {parser.value (multicast_addr_option).trimmed ()} + , parser.values (network_interface_option)}; return app.exec (); } diff --git a/qt_helpers.hpp b/qt_helpers.hpp index aae8c5f07..7170bda0b 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -117,6 +117,32 @@ namespace std } #endif + +inline +bool is_multicast_address (QHostAddress const& host_addr) +{ +#if QT_VERSION >= 0x050600 + return host_addr.isMulticast (); +#else + bool ok; + return (((host_addr.toIPv4Address (&ok) & 0xf0000000u) == 0xe0000000u) && ok) + || host_addr.toIPv6Address ()[0] == 0xff; +#endif +} + +inline +bool is_MAC_ambiguous_multicast_address (QHostAddress const& host_addr) +{ + // sub-ranges 224.128.0.0/24, 225.0.0.0/24, 225.128.0.0/24, + // 226.0.0.0/24, 226.128.0.0/24, ..., 239.0.0.0/24, 239.128.0.0/24 + // are not supported as they are inefficient due to ambiguous + // mappings to Ethernet MAC addresses. 224.0.0.0/24 alone is allowed + // from these ranges + bool ok; + auto ipv4 = host_addr.toIPv4Address (&ok); + return ok && !((ipv4 & 0xffffff00u) == 0xe0000000) && (ipv4 & 0xf07fff00) == 0xe0000000; +} + // Register some useful Qt types with QMetaType Q_DECLARE_METATYPE (QHostAddress); diff --git a/tests/test_qt_helpers.cpp b/tests/test_qt_helpers.cpp index cb6744df2..195c16e0d 100644 --- a/tests/test_qt_helpers.cpp +++ b/tests/test_qt_helpers.cpp @@ -131,6 +131,80 @@ private: QDateTime dt {QDate {2020, 8, 6}, QTime {14, 15, 22, 501}}; QCOMPARE (qt_truncate_date_time_to (dt, 7500), QDateTime (QDate (2020, 8, 6), QTime (14, 15, 22, 500))); } + + Q_SLOT void is_multicast_address_data () + { + QTest::addColumn ("addr"); + QTest::addColumn ("result"); + + QTest::newRow ("loopback") << "127.0.0.1" << false; + QTest::newRow ("looback IPv6") << "::1" << false; + QTest::newRow ("lowest-") << "223.255.255.255" << false; + QTest::newRow ("lowest") << "224.0.0.0" << true; + QTest::newRow ("lowest- IPv6") << "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << false; + QTest::newRow ("lowest IPv6") << "ff00::" << true; + QTest::newRow ("highest") << "239.255.255.255" << true; + QTest::newRow ("highest+") << "240.0.0.0" << false; + QTest::newRow ("highest IPv6") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << true; + } + + Q_SLOT void is_multicast_address () + { + QFETCH (QString, addr); + QFETCH (bool, result); + + QCOMPARE (::is_multicast_address (QHostAddress {addr}), result); + } + + Q_SLOT void is_MAC_ambiguous_multicast_address_data () + { + QTest::addColumn ("addr"); + QTest::addColumn ("result"); + + QTest::newRow ("loopback") << "127.0.0.1" << false; + QTest::newRow ("looback IPv6") << "::1" << false; + + QTest::newRow ("lowest- R1") << "223.255.255.255" << false; + QTest::newRow ("lowest R1") << "224.0.0.0" << false; + QTest::newRow ("highest R1") << "224.0.0.255" << false; + QTest::newRow ("highest+ R1") << "224.0.1.0" << false; + QTest::newRow ("lowest- R1A") << "224.127.255.255" << false; + QTest::newRow ("lowest R1A") << "224.128.0.0" << true; + QTest::newRow ("highest R1A") << "224.128.0.255" << true; + QTest::newRow ("highest+ R1A") << "224.128.1.0" << false; + + QTest::newRow ("lowest- R2") << "224.255.255.255" << false; + QTest::newRow ("lowest R2") << "225.0.0.0" << true; + QTest::newRow ("highest R2") << "225.0.0.255" << true; + QTest::newRow ("highest+ R2") << "225.0.1.0" << false; + QTest::newRow ("lowest- R2A") << "225.127.255.255" << false; + QTest::newRow ("lowest R2A") << "225.128.0.0" << true; + QTest::newRow ("highest R2A") << "225.128.0.255" << true; + QTest::newRow ("highest+ R2A") << "225.128.1.0" << false; + + QTest::newRow ("lowest- R3") << "238.255.255.255" << false; + QTest::newRow ("lowest R3") << "239.0.0.0" << true; + QTest::newRow ("highest R3") << "239.0.0.255" << true; + QTest::newRow ("highest+ R3") << "239.0.1.0" << false; + QTest::newRow ("lowest- R3A") << "239.127.255.255" << false; + QTest::newRow ("lowest R3A") << "239.128.0.0" << true; + QTest::newRow ("highest R3A") << "239.128.0.255" << true; + QTest::newRow ("highest+ R3A") << "239.128.1.0" << false; + + QTest::newRow ("lowest- IPv6") << "feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << false; + QTest::newRow ("lowest IPv6") << "ff00::" << false; + QTest::newRow ("highest") << "239.255.255.255" << false; + QTest::newRow ("highest+") << "240.0.0.0" << false; + QTest::newRow ("highest IPv6") << "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" << false; + } + + Q_SLOT void is_MAC_ambiguous_multicast_address () + { + QFETCH (QString, addr); + QFETCH (bool, result); + + QCOMPARE (::is_MAC_ambiguous_multicast_address (QHostAddress {addr}), result); + } }; QTEST_MAIN (TestQtHelpers); diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index be5062fa0..e40009cb4 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -417,6 +417,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_messageClient {new MessageClient {QApplication::applicationName (), version (), revision (), m_config.udp_server_name (), m_config.udp_server_port (), + m_config.udp_interface_name (), m_config.udp_TTL (), this}}, m_psk_Reporter {&m_config, QString {"WSJT-X v" + version () + " " + m_revision}.simplified ()}, m_manual {&m_network_manager}, @@ -785,6 +786,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, connect (&m_config, &Configuration::transceiver_failure, this, &MainWindow::handle_transceiver_failure); connect (&m_config, &Configuration::udp_server_changed, m_messageClient, &MessageClient::set_server); connect (&m_config, &Configuration::udp_server_port_changed, m_messageClient, &MessageClient::set_server_port); + connect (&m_config, &Configuration::udp_TTL_changed, m_messageClient, &MessageClient::set_TTL); connect (&m_config, &Configuration::accept_udp_requests_changed, m_messageClient, &MessageClient::enable); connect (&m_config, &Configuration::enumerating_audio_devices, [this] () { showStatusMessage (tr ("Enumerating audio devices")); @@ -7835,7 +7837,7 @@ void MainWindow::networkError (QString const& e) , MessageBox::Cancel)) { // retry server lookup - m_messageClient->set_server (m_config.udp_server_name ()); + m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_name ()); } } From 7b54428a60c9956ab9c7a77d3ff22ea693296a47 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 2 Nov 2020 21:35:48 +0000 Subject: [PATCH 54/73] Extend UDP MessageServer client mapping key with the host address The UDP Example reference applications now work correctly with WSJT-X instances with duplicate --rig-name= command line arguments so long as duplicate instances are run on unique hosts. --- UDPExamples/BeaconsModel.cpp | 19 +-- UDPExamples/BeaconsModel.hpp | 6 +- UDPExamples/ClientWidget.cpp | 78 ++++++------- UDPExamples/ClientWidget.hpp | 34 +++--- UDPExamples/DecodesModel.cpp | 26 +++-- UDPExamples/DecodesModel.hpp | 10 +- UDPExamples/MessageAggregatorMainWindow.cpp | 28 +++-- UDPExamples/MessageAggregatorMainWindow.hpp | 10 +- UDPExamples/MessageServer.cpp | 122 ++++++++++---------- UDPExamples/MessageServer.hpp | 63 +++++----- UDPExamples/UDPDaemon.cpp | 72 +++++++----- 11 files changed, 251 insertions(+), 217 deletions(-) diff --git a/UDPExamples/BeaconsModel.cpp b/UDPExamples/BeaconsModel.cpp index 7ac1323a1..8a6cdd279 100644 --- a/UDPExamples/BeaconsModel.cpp +++ b/UDPExamples/BeaconsModel.cpp @@ -25,10 +25,13 @@ namespace QFont text_font {"Courier", 10}; - QList make_row (QString const& client_id, QTime time, qint32 snr, float delta_time + QList make_row (MessageServer::ClientKey const& key, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { + auto client_item = new QStandardItem {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; + client_item->setData (QVariant::fromValue (key)); + auto time_item = new QStandardItem {time.toString ("hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -60,7 +63,7 @@ namespace live->setTextAlignment (Qt::AlignHCenter); QList row { - new QStandardItem {client_id}, time_item, snr_item, dt, freq, dri, gd, pwr, live, new QStandardItem {callsign}}; + client_item, time_item, snr_item, dt, freq, dri, gd, pwr, live, new QStandardItem {callsign}}; Q_FOREACH (auto& item, row) { item->setEditable (false); @@ -81,7 +84,7 @@ BeaconsModel::BeaconsModel (QObject * parent) } } -void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time +void BeaconsModel::add_beacon_spot (bool is_new, ClientKey const& key, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { @@ -90,7 +93,7 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime int target_row {-1}; for (auto row = 0; row < rowCount (); ++row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { auto row_time = item (row, 1)->data ().toTime (); if (row_time == time @@ -113,19 +116,19 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); + insertRow (target_row + 1, make_row (key, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); + appendRow (make_row (key, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); } -void BeaconsModel::decodes_cleared (QString const& client_id) +void BeaconsModel::decodes_cleared (ClientKey const& key) { for (auto row = rowCount () - 1; row >= 0; --row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { removeRow (row); } diff --git a/UDPExamples/BeaconsModel.hpp b/UDPExamples/BeaconsModel.hpp index b089349cc..2baa99ec3 100644 --- a/UDPExamples/BeaconsModel.hpp +++ b/UDPExamples/BeaconsModel.hpp @@ -26,13 +26,15 @@ class BeaconsModel { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit BeaconsModel (QObject * parent = nullptr); - Q_SLOT void add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time + Q_SLOT void add_beacon_spot (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign, QString const& grid , qint32 power, bool off_air); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const&); }; #endif diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index b2ee03609..3be8c788c 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -27,9 +27,9 @@ namespace } } -ClientWidget::IdFilterModel::IdFilterModel (QString const& client_id, QObject * parent) +ClientWidget::IdFilterModel::IdFilterModel (ClientKey const& key, QObject * parent) : QSortFilterProxyModel {parent} - , client_id_ {client_id} + , key_ {key} , rx_df_ (quint32_max) { } @@ -73,7 +73,7 @@ bool ClientWidget::IdFilterModel::filterAcceptsRow (int source_row , QModelIndex const& source_parent) const { auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent); - return sourceModel ()->data (source_index_col0).toString () == client_id_; + return sourceModel ()->data (source_index_col0).value () == key_; } void ClientWidget::IdFilterModel::de_call (QString const& call) @@ -106,9 +106,9 @@ void ClientWidget::IdFilterModel::rx_df (quint32 df) namespace { - QString make_title (QString const& id, QString const& version, QString const& revision) + QString make_title (MessageServer::ClientKey const& key, QString const& version, QString const& revision) { - QString title {id}; + QString title {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; if (version.size ()) { title += QString {" v%1"}.arg (version); @@ -122,14 +122,14 @@ namespace } ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model - , QString const& id, QString const& version, QString const& revision + , ClientKey const& key, QString const& version, QString const& revision , QListWidget const * calls_of_interest, QWidget * parent) - : QDockWidget {make_title (id, version, revision), parent} - , id_ {id} + : QDockWidget {make_title (key, version, revision), parent} + , key_ {key} , done_ {false} , calls_of_interest_ {calls_of_interest} - , decodes_proxy_model_ {id} - , beacons_proxy_model_ {id} + , decodes_proxy_model_ {key} + , beacons_proxy_model_ {key} , erase_action_ {new QAction {tr ("&Erase Band Activity"), this}} , erase_rx_frequency_action_ {new QAction {tr ("Erase &Rx Frequency"), this}} , erase_both_action_ {new QAction {tr ("Erase &Both"), this}} @@ -209,56 +209,56 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod horizontal_layout_->addLayout (subform3_layout_); connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) { - Q_EMIT do_free_text (id_, text, false); + Q_EMIT do_free_text (key_, text, false); }); connect (message_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT do_free_text (id_, message_line_edit_->text (), true); + Q_EMIT do_free_text (key_, message_line_edit_->text (), true); }); connect (grid_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT location (id_, grid_line_edit_->text ()); + Q_EMIT location (key_, grid_line_edit_->text ()); }); connect (configuration_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT switch_configuration (id_, configuration_line_edit_->text ()); + Q_EMIT switch_configuration (key_, configuration_line_edit_->text ()); }); connect (mode_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, mode_line_edit_->text (), quint32_max, empty, fast_mode () + Q_EMIT configure (key_, mode_line_edit_->text (), quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (frequency_tolerance_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; auto f = frequency_tolerance_spin_box_->specialValueText ().size () ? quint32_max : i; - Q_EMIT configure (id_, empty, f, empty, fast_mode () + Q_EMIT configure (key_, empty, f, empty, fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (submode_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, submode_line_edit_->text (), fast_mode () + Q_EMIT configure (key_, empty, quint32_max, submode_line_edit_->text (), fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (fast_mode_check_box_, &QCheckBox::stateChanged, [this] (int state) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, Qt::Checked == state + Q_EMIT configure (key_, empty, quint32_max, empty, Qt::Checked == state , quint32_max, quint32_max, empty, empty, false); }); connect (tr_period_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , i, quint32_max, empty, empty, false); }); connect (rx_df_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, i, empty, empty, false); }); connect (dx_call_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, dx_call_line_edit_->text (), empty, false); }); connect (dx_grid_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, dx_grid_line_edit_->text (), false); }); @@ -289,14 +289,14 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod halt_tx_button_ = control_button_box_->addButton (tr ("&Halt Tx"), QDialogButtonBox::ActionRole); connect (generate_messages_push_button_, &QAbstractButton::clicked, [this] (bool /*checked*/) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, empty, true); }); connect (auto_off_button_, &QAbstractButton::clicked, [this] (bool /* checked */) { - Q_EMIT do_halt_tx (id_, true); + Q_EMIT do_halt_tx (key_, true); }); connect (halt_tx_button_, &QAbstractButton::clicked, [this] (bool /* checked */) { - Q_EMIT do_halt_tx (id_, false); + Q_EMIT do_halt_tx (key_, false); }); content_layout_->addWidget (control_button_box_); @@ -318,13 +318,13 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // connect context menu actions connect (erase_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_); + Q_EMIT do_clear_decodes (key_); }); connect (erase_rx_frequency_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_, 1); + Q_EMIT do_clear_decodes (key_, 1); }); connect (erase_both_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_, 2); + Q_EMIT do_clear_decodes (key_, 2); }); // connect up table view signals @@ -335,7 +335,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // tell new client about calls of interest for (int row = 0; row < calls_of_interest_->count (); ++row) { - Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow}); + Q_EMIT highlight_callsign (key_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow}); } } @@ -349,7 +349,7 @@ void ClientWidget::closeEvent (QCloseEvent *e) { if (!done_) { - Q_EMIT do_close (id_); + Q_EMIT do_close (key_); e->ignore (); // defer closure until client actually closes } else @@ -363,7 +363,7 @@ ClientWidget::~ClientWidget () for (int row = 0; row < calls_of_interest_->count (); ++row) { // tell client to forget calls of interest - Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text ()); + Q_EMIT highlight_callsign (key_, calls_of_interest_->item (row)->text ()); } } @@ -395,7 +395,7 @@ namespace } } -void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call +void ClientWidget::update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid @@ -403,7 +403,7 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name) { - if (id == id_) + if (key == key_) { fast_mode_check_box_->setChecked (fast_mode); decodes_proxy_model_.de_call (de_call); @@ -447,11 +447,11 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& } } -void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ +void ClientWidget::decode_added (bool /*is_new*/, ClientKey const& key, QTime /*time*/, qint32 /*snr*/ , float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/ , QString const& /*message*/, bool /*low_confidence*/, bool /*off_air*/) { - if (client_id == id_ && !columns_resized_) + if (key == key_ && !columns_resized_) { decodes_stack_->setCurrentIndex (0); decodes_table_view_->resizeColumnsToContents (); @@ -460,12 +460,12 @@ void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTim decodes_table_view_->scrollToBottom (); } -void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ +void ClientWidget::beacon_spot_added (bool /*is_new*/, ClientKey const& key, QTime /*time*/, qint32 /*snr*/ , float /*delta_time*/, Frequency /*delta_frequency*/, qint32 /*drift*/ , QString const& /*callsign*/, QString const& /*grid*/, qint32 /*power*/ , bool /*off_air*/) { - if (client_id == id_ && !columns_resized_) + if (key == key_ && !columns_resized_) { decodes_stack_->setCurrentIndex (1); beacons_table_view_->resizeColumnsToContents (); @@ -474,9 +474,9 @@ void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, beacons_table_view_->scrollToBottom (); } -void ClientWidget::decodes_cleared (QString const& client_id) +void ClientWidget::decodes_cleared (ClientKey const& key) { - if (client_id == id_) + if (key == key_) { columns_resized_ = false; } diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index 983ddd874..ee91d084a 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -35,42 +35,44 @@ class ClientWidget { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model - , QString const& id, QString const& version, QString const& revision + , ClientKey const& key, QString const& version, QString const& revision , QListWidget const * calls_of_interest, QWidget * parent = nullptr); void dispose (); ~ClientWidget (); bool fast_mode () const; - Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call + Q_SLOT void update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name); - Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr + Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); - Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime, qint32 snr + Q_SLOT void beacon_spot_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, Frequency delta_frequency, qint32 drift , QString const& callsign, QString const& grid, qint32 power , bool off_air); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const& key); - Q_SIGNAL void do_clear_decodes (QString const& id, quint8 window = 0); - Q_SIGNAL void do_close (QString const& id); + Q_SIGNAL void do_clear_decodes (ClientKey const& key, quint8 window = 0); + Q_SIGNAL void do_close (ClientKey const& key); Q_SIGNAL void do_reply (QModelIndex const&, quint8 modifier); - Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only); - Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool); - Q_SIGNAL void location (QString const& id, QString const& text); - Q_SIGNAL void highlight_callsign (QString const& id, QString const& call + Q_SIGNAL void do_halt_tx (ClientKey const& key, bool auto_only); + Q_SIGNAL void do_free_text (ClientKey const& key, QString const& text, bool); + Q_SIGNAL void location (ClientKey const& key, QString const& text); + Q_SIGNAL void highlight_callsign (ClientKey const& key, QString const& call , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); - Q_SIGNAL void switch_configuration (QString const& id, QString const& configuration_name); - Q_SIGNAL void configure (QString const& id, QString const& mode, quint32 frequency_tolerance + Q_SIGNAL void switch_configuration (ClientKey const& key, QString const& configuration_name); + Q_SIGNAL void configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages); @@ -79,7 +81,7 @@ private: : public QSortFilterProxyModel { public: - IdFilterModel (QString const& client_id, QObject * = nullptr); + IdFilterModel (ClientKey const& key, QObject * = nullptr); void de_call (QString const&); void rx_df (quint32); @@ -88,7 +90,7 @@ private: private: bool filterAcceptsRow (int source_row, QModelIndex const& source_parent) const override; - QString client_id_; + ClientKey key_; QString call_; QRegularExpression base_call_re_; quint32 rx_df_; @@ -96,7 +98,7 @@ private: void closeEvent (QCloseEvent *) override; - QString id_; + ClientKey key_; bool done_; QListWidget const * calls_of_interest_; IdFilterModel decodes_proxy_model_; diff --git a/UDPExamples/DecodesModel.cpp b/UDPExamples/DecodesModel.cpp index 6121ff31a..7b8d87c52 100644 --- a/UDPExamples/DecodesModel.cpp +++ b/UDPExamples/DecodesModel.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -33,10 +34,13 @@ namespace QFont text_font {"Courier", 10}; - QList make_row (QString const& client_id, QTime time, qint32 snr, float delta_time - , quint32 delta_frequency, QString const& mode, QString const& message - , bool low_confidence, bool off_air, bool is_fast) + QList make_row (MessageServer::ClientKey const& key, QTime time, qint32 snr + , float delta_time, quint32 delta_frequency, QString const& mode + , QString const& message, bool low_confidence, bool off_air, bool is_fast) { + auto client_item = new QStandardItem {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; + client_item->setData (QVariant::fromValue (key)); + auto time_item = new QStandardItem {time.toString (is_fast || "~" == mode ? "hh:mm:ss" : "hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -63,7 +67,7 @@ namespace live->setTextAlignment (Qt::AlignHCenter); QList row { - new QStandardItem {client_id}, time_item, snr_item, dt, df, md, confidence, live, new QStandardItem {message}}; + client_item, time_item, snr_item, dt, df, md, confidence, live, new QStandardItem {message}}; Q_FOREACH (auto& item, row) { item->setEditable (false); @@ -84,7 +88,7 @@ DecodesModel::DecodesModel (QObject * parent) } } -void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time +void DecodesModel::add_decode (bool is_new, ClientKey const& key, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air, bool is_fast) { @@ -93,7 +97,7 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time int target_row {-1}; for (auto row = 0; row < rowCount (); ++row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { auto row_time = item (row, 1)->data ().toTime (); if (row_time == time @@ -115,21 +119,21 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode + insertRow (target_row + 1, make_row (key, time, snr, delta_time, delta_frequency, mode , message, low_confidence, off_air, is_fast)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message, low_confidence + appendRow (make_row (key, time, snr, delta_time, delta_frequency, mode, message, low_confidence , off_air, is_fast)); } -void DecodesModel::decodes_cleared (QString const& client_id) +void DecodesModel::decodes_cleared (ClientKey const& key) { for (auto row = rowCount () - 1; row >= 0; --row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { removeRow (row); } @@ -139,7 +143,7 @@ void DecodesModel::decodes_cleared (QString const& client_id) void DecodesModel::do_reply (QModelIndex const& source, quint8 modifiers) { auto row = source.row (); - Q_EMIT reply (data (index (row, 0)).toString () + Q_EMIT reply (item (row, 0)->data ().value () , item (row, 1)->data ().toTime () , item (row, 2)->data ().toInt () , item (row, 3)->data ().toFloat () diff --git a/UDPExamples/DecodesModel.hpp b/UDPExamples/DecodesModel.hpp index 17c9ae125..27a168c87 100644 --- a/UDPExamples/DecodesModel.hpp +++ b/UDPExamples/DecodesModel.hpp @@ -5,8 +5,6 @@ #include "MessageServer.hpp" -using Frequency = MessageServer::Frequency; - class QTime; class QString; class QModelIndex; @@ -28,16 +26,18 @@ class DecodesModel { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit DecodesModel (QObject * parent = nullptr); - Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time + Q_SLOT void add_decode (bool is_new, ClientKey const&, QTime, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air, bool is_fast); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const&); Q_SLOT void do_reply (QModelIndex const& source, quint8 modifiers); - Q_SIGNAL void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency + Q_SIGNAL void reply (ClientKey const&, QTime, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence, quint8 modifiers); }; diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index ba034b0e2..7e74342c0 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -184,13 +184,16 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () connect (server_, &MessageServer::client_closed, this, &MessageAggregatorMainWindow::remove_client); connect (server_, &MessageServer::client_closed, decodes_model_, &DecodesModel::decodes_cleared); connect (server_, &MessageServer::client_closed, beacons_model_, &BeaconsModel::decodes_cleared); - connect (server_, &MessageServer::decode, [this] (bool is_new, QString const& id, QTime time + connect (server_, &MessageServer::decode, [this] (bool is_new, ClientKey const& key, QTime time , qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence , bool off_air) { - decodes_model_->add_decode (is_new, id, time, snr, delta_time, delta_frequency, mode, message - , low_confidence, off_air, dock_widgets_[id]->fast_mode ());}); + decodes_model_->add_decode (is_new, key, time, snr, delta_time + , delta_frequency, mode, message + , low_confidence, off_air + , dock_widgets_[key]->fast_mode ()); + }); connect (server_, &MessageServer::WSPR_decode, beacons_model_, &BeaconsModel::add_beacon_spot); connect (server_, &MessageServer::decodes_cleared, decodes_model_, &DecodesModel::decodes_cleared); connect (server_, &MessageServer::decodes_cleared, beacons_model_, &BeaconsModel::decodes_cleared); @@ -207,7 +210,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () show (); } -void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call +void MessageAggregatorMainWindow::log_qso (ClientKey const& /*key*/, QDateTime time_off + , QString const& dx_call , QString const& dx_grid, Frequency dial_frequency, QString const& mode , QString const& report_sent, QString const& report_received , QString const& tx_power, QString const& comments @@ -240,9 +244,9 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time log_table_view_->scrollToBottom (); } -void MessageAggregatorMainWindow::add_client (QString const& id, QString const& version, QString const& revision) +void MessageAggregatorMainWindow::add_client (ClientKey const& key, QString const& version, QString const& revision) { - auto dock = new ClientWidget {decodes_model_, beacons_model_, id, version, revision, calls_of_interest_, this}; + auto dock = new ClientWidget {decodes_model_, beacons_model_, key, version, revision, calls_of_interest_, this}; dock->setAttribute (Qt::WA_DeleteOnClose); auto view_action = dock->toggleViewAction (); view_action->setEnabled (true); @@ -262,13 +266,13 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const& connect (dock, &ClientWidget::highlight_callsign, server_, &MessageServer::highlight_callsign); connect (dock, &ClientWidget::switch_configuration, server_, &MessageServer::switch_configuration); connect (dock, &ClientWidget::configure, server_, &MessageServer::configure); - dock_widgets_[id] = dock; - server_->replay (id); // request decodes and status + dock_widgets_[key] = dock; + server_->replay (key); // request decodes and status } -void MessageAggregatorMainWindow::remove_client (QString const& id) +void MessageAggregatorMainWindow::remove_client (ClientKey const& key) { - auto iter = dock_widgets_.find (id); + auto iter = dock_widgets_.find (key); if (iter != std::end (dock_widgets_)) { (*iter)->dispose (); @@ -287,9 +291,9 @@ MessageAggregatorMainWindow::~MessageAggregatorMainWindow () void MessageAggregatorMainWindow::change_highlighting (QString const& call, QColor const& bg, QColor const& fg , bool last_only) { - for (auto id : dock_widgets_.keys ()) + for (auto key : dock_widgets_.keys ()) { - server_->highlight_callsign (id, call, bg, fg, last_only); + server_->highlight_callsign (key, call, bg, fg, last_only); } } diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 045f4e945..445a5908e 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -24,11 +24,13 @@ class MessageAggregatorMainWindow { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: MessageAggregatorMainWindow (); ~MessageAggregatorMainWindow (); - Q_SLOT void log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SLOT void log_qso (ClientKey const&, QDateTime time_off, QString const& dx_call, QString const& dx_grid , Frequency dial_frequency, QString const& mode, QString const& report_sent , QString const& report_received, QString const& tx_power, QString const& comments , QString const& name, QDateTime time_on, QString const& operator_call @@ -36,13 +38,13 @@ public: , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); private: - void add_client (QString const& id, QString const& version, QString const& revision); - void remove_client (QString const& id); + void add_client (ClientKey const&, QString const& version, QString const& revision); + void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, bool last_only = false); // maps client id to widgets - using ClientsDictionary = QHash; + using ClientsDictionary = QHash; ClientsDictionary dock_widgets_; QStandardItemModel * log_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index fc36aad9d..8869c4b89 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -83,9 +83,8 @@ public: struct Client { Client () = default; - Client (QHostAddress const& sender_address, port_type const& sender_port) - : sender_address_ {sender_address} - , sender_port_ {sender_port} + Client (port_type const& sender_port) + : sender_port_ {sender_port} , negotiated_schema_number_ {2} // not 1 because it's broken , last_activity_ {QDateTime::currentDateTime ()} { @@ -93,12 +92,11 @@ public: Client (Client const&) = default; Client& operator= (Client const&) = default; - QHostAddress sender_address_; port_type sender_port_; quint32 negotiated_schema_number_; QDateTime last_activity_; }; - QHash clients_; // maps id to Client + QHash clients_; // maps id to Client QTimer * clock_; }; @@ -171,9 +169,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s auto id = in.id (); if (OK == check_status (in)) { - if (!clients_.contains (id)) + auto client_key = ClientKey {sender, id}; + if (!clients_.contains (client_key)) { - auto& client = (clients_[id] = {sender, sender_port}); + auto& client = (clients_[client_key] = {sender_port}); QByteArray client_version; QByteArray client_revision; @@ -194,7 +193,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s << version_.toUtf8 () << revision_.toUtf8 (); if (impl::OK == check_status (hb)) { - writeDatagram (message, client.sender_address_, client.sender_port_); + writeDatagram (message, client_key.first, sender_port); } else { @@ -204,10 +203,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s // we don't care if this fails to read in >> client_version >> client_revision; } - Q_EMIT self_->client_opened (id, QString::fromUtf8 (client_version), + Q_EMIT self_->client_opened (client_key, QString::fromUtf8 (client_version), QString::fromUtf8 (client_revision)); } - clients_[id].last_activity_ = QDateTime::currentDateTime (); + clients_[client_key].last_activity_ = QDateTime::currentDateTime (); // // message format is described in NetworkMessage.hpp @@ -219,7 +218,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s break; case NetworkMessage::Clear: - Q_EMIT self_->decodes_cleared (id); + Q_EMIT self_->decodes_cleared (client_key); break; case NetworkMessage::Status: @@ -250,7 +249,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name; if (check_status (in) != Fail) { - Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) + Q_EMIT self_->status_update (client_key, f, QString::fromUtf8 (mode) + , QString::fromUtf8 (dx_call) , QString::fromUtf8 (report), QString::fromUtf8 (tx_mode) , tx_enabled, transmitting, decoding, rx_df, tx_df , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) @@ -278,7 +278,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> message >> low_confidence >> off_air; if (check_status (in) != Fail) { - Q_EMIT self_->decode (is_new, id, time, snr, delta_time, delta_frequency + Q_EMIT self_->decode (is_new, client_key, time, snr, delta_time, delta_frequency , QString::fromUtf8 (mode), QString::fromUtf8 (message) , low_confidence, off_air); } @@ -302,7 +302,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> off_air; if (check_status (in) != Fail) { - Q_EMIT self_->WSPR_decode (is_new, id, time, snr, delta_time, frequency, drift + Q_EMIT self_->WSPR_decode (is_new, client_key, time, snr, delta_time, frequency, drift , QString::fromUtf8 (callsign), QString::fromUtf8 (grid) , power, off_air); } @@ -333,8 +333,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> exchange_sent >> exchange_rcvd >> prop_mode; if (check_status (in) != Fail) { - Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid) - , dial_frequency, QString::fromUtf8 (mode), QString::fromUtf8 (report_sent) + Q_EMIT self_->qso_logged (client_key, time_off, QString::fromUtf8 (dx_call) + , QString::fromUtf8 (dx_grid) + , dial_frequency, QString::fromUtf8 (mode) + , QString::fromUtf8 (report_sent) , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power) , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call) @@ -345,8 +347,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s break; case NetworkMessage::Close: - Q_EMIT self_->client_closed (id); - clients_.remove (id); + Q_EMIT self_->client_closed (client_key); + clients_.remove (client_key); break; case NetworkMessage::LoggedADIF: @@ -355,7 +357,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s in >> ADIF; if (check_status (in) != Fail) { - Q_EMIT self_->logged_ADIF (id, ADIF); + Q_EMIT self_->logged_ADIF (client_key, ADIF); } } break; @@ -388,7 +390,7 @@ void MessageServer::impl::tick () { if (now > (*iter).last_activity_.addSecs (NetworkMessage::pulse)) { - Q_EMIT self_->clear_decodes (iter.key ()); + Q_EMIT self_->decodes_cleared (iter.key ()); Q_EMIT self_->client_closed (iter.key ()); iter = clients_.erase (iter); // safe while iterating as doesn't rehash } @@ -462,127 +464,127 @@ void MessageServer::start (port_type port, QHostAddress const& multicast_group_a } } -void MessageServer::clear_decodes (QString const& id, quint8 window) +void MessageServer::clear_decodes (ClientKey const& key, quint8 window) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Clear, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Clear, key.second, (*iter).negotiated_schema_number_}; out << window; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time +void MessageServer::reply (ClientKey const& key, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode , QString const& message_text, bool low_confidence, quint8 modifiers) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Reply, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Reply, key.second, (*iter).negotiated_schema_number_}; out << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 () << low_confidence << modifiers; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::replay (QString const& id) +void MessageServer::replay (ClientKey const& key) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Replay, id, (*iter).negotiated_schema_number_}; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + NetworkMessage::Builder out {&message, NetworkMessage::Replay, key.second, (*iter).negotiated_schema_number_}; + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::close (QString const& id) +void MessageServer::close (ClientKey const& key) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Close, id, (*iter).negotiated_schema_number_}; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + NetworkMessage::Builder out {&message, NetworkMessage::Close, key.second, (*iter).negotiated_schema_number_}; + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::halt_tx (QString const& id, bool auto_only) +void MessageServer::halt_tx (ClientKey const& key, bool auto_only) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, key.second, (*iter).negotiated_schema_number_}; out << auto_only; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::free_text (QString const& id, QString const& text, bool send) +void MessageServer::free_text (ClientKey const& key, QString const& text, bool send) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::FreeText, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::FreeText, key.second, (*iter).negotiated_schema_number_}; out << text.toUtf8 () << send; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::location (QString const& id, QString const& loc) +void MessageServer::location (ClientKey const& key, QString const& loc) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Location, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Location, key.second, (*iter).negotiated_schema_number_}; out << loc.toUtf8 (); - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::highlight_callsign (QString const& id, QString const& callsign +void MessageServer::highlight_callsign (ClientKey const& key, QString const& callsign , QColor const& bg, QColor const& fg, bool last_only) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, key.second, (*iter).negotiated_schema_number_}; out << callsign.toUtf8 () << bg << fg << last_only; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::switch_configuration (QString const& id, QString const& configuration_name) +void MessageServer::switch_configuration (ClientKey const& key, QString const& configuration_name) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, key.second, (*iter).negotiated_schema_number_}; out << configuration_name.toUtf8 (); - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::configure (QString const& id, QString const& mode, quint32 frequency_tolerance +void MessageServer::configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Configure, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Configure, key.second, (*iter).negotiated_schema_number_}; out << mode.toUtf8 () << frequency_tolerance << submode.toUtf8 () << fast_mode << tr_period << rx_df << dx_call.toUtf8 () << dx_grid.toUtf8 () << generate_messages; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 449c70f4b..8a31e7bd5 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -2,6 +2,7 @@ #define MESSAGE_SERVER_HPP__ #include +#include #include #include #include @@ -33,6 +34,7 @@ class UDP_EXPORT MessageServer public: using port_type = quint16; using Frequency = Radio::Frequency; + using ClientKey = QPair; MessageServer (QObject * parent = nullptr, QString const& version = QString {}, QString const& revision = QString {}); @@ -45,73 +47,72 @@ public: , QStringList const& network_interface_names = QStringList {}); // ask the client to clear one or both of the decode windows - Q_SLOT void clear_decodes (QString const& id, quint8 window = 0); + Q_SLOT void clear_decodes (ClientKey const&, quint8 window = 0); // ask the client with identification 'id' to make the same action // as a double click on the decode would // // note that the client is not obliged to take any action and only // takes any action if the decode is present and is a CQ or QRZ message - Q_SLOT void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency + Q_SLOT void reply (ClientKey const&, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence, quint8 modifiers); - // ask the client with identification 'id' to close down gracefully - Q_SLOT void close (QString const& id); + // ask the client to close down gracefully + Q_SLOT void close (ClientKey const&); - // ask the client with identification 'id' to replay all decodes - Q_SLOT void replay (QString const& id); + // ask the client to replay all decodes + Q_SLOT void replay (ClientKey const&); - // ask the client with identification 'id' to halt transmitting - // auto_only just disables auto Tx, otherwise halt is immediate - Q_SLOT void halt_tx (QString const& id, bool auto_only); + // ask the client to halt transmitting auto_only just disables auto + // Tx, otherwise halt is immediate + Q_SLOT void halt_tx (ClientKey const&, bool auto_only); - // ask the client with identification 'id' to set the free text - // message and optionally send it ASAP - Q_SLOT void free_text (QString const& id, QString const& text, bool send); + // ask the client to set the free text message and optionally send + // it ASAP + Q_SLOT void free_text (ClientKey const&, QString const& text, bool send); - // ask the client with identification 'id' to set the location provided - Q_SLOT void location (QString const& id, QString const& location); + // ask the client to set the location provided + Q_SLOT void location (ClientKey const&, QString const& location); - // ask the client with identification 'id' to highlight the callsign - // specified with the given colors - Q_SLOT void highlight_callsign (QString const& id, QString const& callsign + // ask the client to highlight the callsign specified with the given + // colors + Q_SLOT void highlight_callsign (ClientKey const&, QString const& callsign , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); - // ask the client with identification 'id' to switch to - // configuration 'configuration_name' - Q_SLOT void switch_configuration (QString const& id, QString const& configuration_name); + // ask the client to switch to configuration 'configuration_name' + Q_SLOT void switch_configuration (ClientKey const&, QString const& configuration_name); - // ask the client with identification 'id' to change configuration - Q_SLOT void configure (QString const& id, QString const& mode, quint32 frequency_tolerance + // ask the client to change configuration + Q_SLOT void configure (ClientKey const&, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages); // the following signals are emitted when a client broadcasts the // matching message - Q_SIGNAL void client_opened (QString const& id, QString const& version, QString const& revision); - Q_SIGNAL void status_update (QString const& id, Frequency, QString const& mode, QString const& dx_call + Q_SIGNAL void client_opened (ClientKey const&, QString const& version, QString const& revision); + Q_SIGNAL void status_update (ClientKey const&, Frequency, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name); - Q_SIGNAL void client_closed (QString const& id); - Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time + Q_SIGNAL void client_closed (ClientKey const&); + Q_SIGNAL void decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air); - Q_SIGNAL void WSPR_decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time, Frequency + Q_SIGNAL void WSPR_decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time, Frequency , qint32 drift, QString const& callsign, QString const& grid, qint32 power , bool off_air); - Q_SIGNAL void qso_logged (QString const& id, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SIGNAL void qso_logged (ClientKey const&, QDateTime time_off, QString const& dx_call, QString const& dx_grid , Frequency dial_frequency, QString const& mode, QString const& report_sent , QString const& report_received, QString const& tx_power, QString const& comments , QString const& name, QDateTime time_on, QString const& operator_call , QString const& my_call, QString const& my_grid , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); - Q_SIGNAL void decodes_cleared (QString const& id); - Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF); + Q_SIGNAL void decodes_cleared (ClientKey const&); + Q_SIGNAL void logged_ADIF (ClientKey const&, QByteArray const& ADIF); // this signal is emitted when a network error occurs Q_SIGNAL void error (QString const&) const; @@ -121,4 +122,6 @@ private: pimpl m_; }; +Q_DECLARE_METATYPE (MessageServer::ClientKey); + #endif diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2668a6021..b7620ec90 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -41,15 +41,17 @@ class Client { Q_OBJECT + using ClientKey = MessageServer::ClientKey; + public: - explicit Client (QString const& id, QObject * parent = nullptr) + explicit Client (ClientKey const& key, QObject * parent = nullptr) : QObject {parent} - , id_ {id} + , key_ {key} , dial_frequency_ {0u} { } - Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& /*dx_call*/ + Q_SLOT void update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& /*dx_call*/ , QString const& /*report*/, QString const& /*tx_mode*/, bool /*tx_enabled*/ , bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*tx_df*/ , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ @@ -57,67 +59,73 @@ public: , quint8 /*special_op_mode*/, quint32 /*frequency_tolerance*/, quint32 /*tr_period*/ , QString const& /*configuration_name*/) { - if (id == id_) + if (key == key_) { if (f != dial_frequency_) { - std::cout << tr ("%1: Dial frequency changed to %2").arg (id_).arg (f).toStdString () << std::endl; + std::cout << tr ("%1(%2): Dial frequency changed to %3") + .arg (key_.second).arg (key_.first.toString ()).arg (f).toStdString () << std::endl; dial_frequency_ = f; } if (mode + sub_mode != mode_) { - std::cout << tr ("%1: Mode changed to %2").arg (id_).arg (mode + sub_mode).toStdString () << std::endl; + std::cout << tr ("%1(%2): Mode changed to %3") + .arg (key_.second).arg (key_.first.toString ()).arg (mode + sub_mode).toStdString () << std::endl; mode_ = mode + sub_mode; } } } - Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime time, qint32 snr + Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime time, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air) { - if (client_id == id_) + if (key == key_) { qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high") << "On air:" << !off_air; - std::cout << tr ("%1: Decoded %2").arg (id_).arg (message).toStdString () << std::endl; + std::cout << tr ("%1(%2): Decoded %3") + .arg (key_.second).arg (key_.first.toString ()).arg (message).toStdString () << std::endl; } } - Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime time, qint32 snr + Q_SLOT void beacon_spot_added (bool is_new, ClientKey const& key, QTime time, qint32 snr , float delta_time, Frequency delta_frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { - if (client_id == id_) + if (key == key_) { qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "drift:" << drift; - std::cout << tr ("%1: WSPR decode %2 grid %3 power: %4").arg (id_).arg (callsign).arg (grid).arg (power).toStdString () + std::cout << tr ("%1(%2): WSPR decode %3 grid %4 power: %5") + .arg (key_.second).arg (key_.first.toString ()).arg (callsign).arg (grid).arg (power).toStdString () << "On air:" << !off_air << std::endl; } } - Q_SLOT void qso_logged (QString const&client_id, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SLOT void qso_logged (ClientKey const& key, QDateTime time_off, QString const& dx_call, QString const& dx_grid , Frequency dial_frequency, QString const& mode, QString const& report_sent , QString const& report_received, QString const& tx_power , QString const& comments, QString const& name, QDateTime time_on , QString const& operator_call, QString const& my_call, QString const& my_grid , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode) { - if (client_id == id_) + if (key == key_) { - qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" << dx_call << "grid:" << dx_grid + qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" + << dx_call << "grid:" << dx_grid << "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent << "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments << "name:" << name << "operator_call:" << operator_call << "my_call:" << my_call << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent << "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode; std::cout << QByteArray {80, '-'}.data () << '\n'; - std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 time_off: %8 op: %9 my_call: %10 my_grid: %11 exchange_sent: %12 exchange_rcvd: %13 comments: %14 prop_mode: %15") - .arg (id_).arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received) + std::cout << tr ("%1(%2): Logged %3 grid: %4 power: %5 sent: %6 recd: %7 freq: %8 time_off: %9 op: %10 my_call: %11 my_grid: %12 exchange_sent: %13 exchange_rcvd: %14 comments: %15 prop_mode: %16") + .arg (key_.second).arg (key.first.toString ()).arg (dx_call).arg (dx_grid).arg (tx_power) + .arg (report_sent).arg (report_received) .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) .arg (comments).arg (prop_mode).toStdString () @@ -125,9 +133,9 @@ public: } } - Q_SLOT void logged_ADIF (QString const&client_id, QByteArray const& ADIF) + Q_SLOT void logged_ADIF (ClientKey const& key, QByteArray const& ADIF) { - if (client_id == id_) + if (key == key_) { qDebug () << "ADIF:" << ADIF; std::cout << QByteArray {80, '-'}.data () << '\n'; @@ -136,7 +144,7 @@ public: } private: - QString id_; + ClientKey key_; Frequency dial_frequency_; QString mode_; }; @@ -146,6 +154,8 @@ class Server { Q_OBJECT + using ClientKey = MessageServer::ClientKey; + public: Server (port_type port, QHostAddress const& multicast_group, QStringList const& network_interface_names) : server_ {new MessageServer {this}} @@ -161,17 +171,18 @@ public: } private: - void add_client (QString const& id, QString const& version, QString const& revision) + void add_client (ClientKey const& key, QString const& version, QString const& revision) { - auto client = new Client {id}; + auto client = new Client {key}; connect (server_, &MessageServer::status_update, client, &Client::update_status); connect (server_, &MessageServer::decode, client, &Client::decode_added); connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added); connect (server_, &MessageServer::qso_logged, client, &Client::qso_logged); connect (server_, &MessageServer::logged_ADIF, client, &Client::logged_ADIF); - clients_[id] = client; - server_->replay (id); - std::cout << "Discovered WSJT-X instance: " << id.toStdString (); + clients_[key] = client; + server_->replay (key); + std::cout << "Discovered WSJT-X instance: " << key.second.toStdString () + << '(' << key.first.toString ().toStdString () << ')'; if (version.size ()) { std::cout << " v" << version.toStdString (); @@ -183,21 +194,22 @@ private: std::cout << std::endl; } - void remove_client (QString const& id) + void remove_client (ClientKey const& key) { - auto iter = clients_.find (id); + auto iter = clients_.find (key); if (iter != std::end (clients_)) { clients_.erase (iter); (*iter)->deleteLater (); } - std::cout << "Removed WSJT-X instance: " << id.toStdString () << std::endl; + std::cout << "Removed WSJT-X instance: " << key.second.toStdString () + << '(' << key.first.toString ().toStdString () << ')' << std::endl; } MessageServer * server_; - // maps client id to clients - QHash clients_; + // maps client key to clients + QHash clients_; }; #include "UDPDaemon.moc" From f9aa10f3a5795e795aef2cbfbd12311126d20eb6 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Mon, 2 Nov 2020 22:08:37 +0000 Subject: [PATCH 55/73] UDPDaemon command line flag to list network interfaces --- UDPExamples/UDPDaemon.cpp | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index b7620ec90..2044bfb00 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -17,12 +17,14 @@ #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -212,6 +214,42 @@ private: QHash clients_; }; +void list_interfaces () +{ + for (auto const& net_if : QNetworkInterface::allInterfaces ()) + { + if (net_if.flags () & QNetworkInterface::IsUp) + { + std::cout << net_if.humanReadableName ().toStdString () << ":\n" + " id: " << net_if.name ().toStdString () << " (" << net_if.index () << ")\n" + " addr: " << net_if.hardwareAddress ().toStdString () << "\n" + " flags: "; + if (net_if.flags () & QNetworkInterface::IsRunning) + { + std::cout << "Running "; + } + if (net_if.flags () & QNetworkInterface::CanBroadcast) + { + std::cout << "Broadcast "; + } + if (net_if.flags () & QNetworkInterface::CanMulticast) + { + std::cout << "Multicast "; + } + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + std::cout << "Loop-back "; + } + std::cout << "\n addresses:\n"; + for (auto const& ae : net_if.addressEntries ()) + { + std::cout << " " << ae.ip ().toString ().toStdString () << '\n'; + } + std::cout << '\n'; + } + } +} + #include "UDPDaemon.moc" int main (int argc, char * argv[]) @@ -232,6 +270,11 @@ int main (int argc, char * argv[]) auto help_option = parser.addHelpOption (); auto version_option = parser.addVersionOption (); + QCommandLineOption list_option (QStringList {"l", "list-interfaces"}, + app.translate ("UDPDaemon", + "Print the available network interfaces.")); + parser.addOption (list_option); + QCommandLineOption port_option (QStringList {"p", "port"}, app.translate ("UDPDaemon", "Where is the UDP service port number to listen on.\n" @@ -257,6 +300,12 @@ int main (int argc, char * argv[]) parser.process (app); + if (parser.isSet (list_option)) + { + list_interfaces (); + return EXIT_SUCCESS; + } + Server server {static_cast (parser.value (port_option).toUInt ()) , QHostAddress {parser.value (multicast_addr_option).trimmed ()} , parser.values (network_interface_option)}; From 4e0e23c301145f13c400c3fb91dcc593c5b77fdb Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 20:28:29 +0000 Subject: [PATCH 56/73] New combo box with a list of checkable items --- CMakeLists.txt | 1 + widgets/CheckableItemComboBox.cpp | 93 +++++++++++++++++++++++++++++++ widgets/CheckableItemComboBox.hpp | 36 ++++++++++++ widgets/widgets.pri | 7 ++- 4 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 widgets/CheckableItemComboBox.cpp create mode 100644 widgets/CheckableItemComboBox.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 331194711..5b07684e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -241,6 +241,7 @@ set (wsjt_qt_CXXSRCS logbook/Multiplier.cpp Network/NetworkAccessManager.cpp widgets/LazyFillComboBox.cpp + widgets/CheckableItemComboBox.cpp ) set (wsjt_qtmm_CXXSRCS diff --git a/widgets/CheckableItemComboBox.cpp b/widgets/CheckableItemComboBox.cpp new file mode 100644 index 000000000..3ef926243 --- /dev/null +++ b/widgets/CheckableItemComboBox.cpp @@ -0,0 +1,93 @@ +#include "CheckableItemComboBox.hpp" + +#include +#include +#include +#include +#include +#include + +class CheckableItemComboBoxStyledItemDelegate + : public QStyledItemDelegate +{ +public: + explicit CheckableItemComboBoxStyledItemDelegate (QObject * parent = nullptr) + : QStyledItemDelegate {parent} + { + } + + void paint (QPainter * painter, QStyleOptionViewItem const& option, QModelIndex const& index) const override + { + QStyleOptionViewItem& mutable_option = const_cast (option); + mutable_option.showDecorationSelected = false; + QStyledItemDelegate::paint (painter, mutable_option, index); + } +}; + +CheckableItemComboBox::CheckableItemComboBox (QWidget * parent) + : QComboBox {parent} + , model_ {new QStandardItemModel()} +{ + setModel (model_.data ()); + + setEditable (true); + lineEdit ()->setReadOnly (true); + lineEdit ()->installEventFilter (this); + setItemDelegate (new CheckableItemComboBoxStyledItemDelegate {this}); + + connect (lineEdit(), &QLineEdit::selectionChanged, lineEdit(), &QLineEdit::deselect); + connect (static_cast (view ()), &QListView::pressed, this, &CheckableItemComboBox::item_pressed); + connect (model_.data (), &QStandardItemModel::dataChanged, this, &CheckableItemComboBox::model_data_changed); +} + +QStandardItem * CheckableItemComboBox::addCheckItem (QString const& label, QVariant const& data + , Qt::CheckState checkState) +{ + auto * item = new QStandardItem {label}; + item->setCheckState (checkState); + item->setData (data); + item->setFlags (Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + model_->appendRow (item); + update_text (); + return item; +} + +bool CheckableItemComboBox::eventFilter (QObject * object, QEvent * event) +{ + if (object == lineEdit() && event->type () == QEvent::MouseButtonPress) + { + showPopup(); + return true; + } + return false; +} + +void CheckableItemComboBox::update_text() +{ + QString text; + for (int i = 0; i < model_->rowCount (); ++i) + { + if (model_->item (i)->checkState () == Qt::Checked) + { + if (text.size ()) + { + text+= ", "; + } + text += model_->item (i)->data ().toString (); + } + } + lineEdit ()->setText (text); +} + +void CheckableItemComboBox::model_data_changed () +{ + update_text (); +} + +void CheckableItemComboBox::item_pressed (QModelIndex const& index) +{ + QStandardItem * item = model_->itemFromIndex (index); + item->setCheckState (item->checkState () == Qt::Checked ? Qt::Unchecked : Qt::Checked); +} + +#include "widgets/moc_CheckableItemComboBox.cpp" diff --git a/widgets/CheckableItemComboBox.hpp b/widgets/CheckableItemComboBox.hpp new file mode 100644 index 000000000..2aa3e9831 --- /dev/null +++ b/widgets/CheckableItemComboBox.hpp @@ -0,0 +1,36 @@ +#ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__ +#define CHECKABLE_ITEM_COMBO_BOX_HPP__ + +#include +#include + +class QStandardItemModel; +class QStandardItem; + +/** + * @brief QComboBox with support of checkboxes + * http://stackoverflow.com/questions/8422760/combobox-of-checkboxes + */ +class CheckableItemComboBox + : public QComboBox +{ + Q_OBJECT + +public: + explicit CheckableItemComboBox (QWidget * parent = nullptr); + QStandardItem * addCheckItem (QString const& label, QVariant const& data, Qt::CheckState checkState); + +protected: + bool eventFilter (QObject *, QEvent *) override; + +private: + void update_text(); + + Q_SLOT void model_data_changed (); + Q_SLOT void item_pressed (QModelIndex const&); + +private: + QScopedPointer model_; +}; + +#endif diff --git a/widgets/widgets.pri b/widgets/widgets.pri index 7a364c4ee..6a623d825 100644 --- a/widgets/widgets.pri +++ b/widgets/widgets.pri @@ -10,7 +10,9 @@ SOURCES += \ widgets/AbstractLogWindow.cpp \ widgets/FrequencyLineEdit.cpp widgets/FrequencyDeltaLineEdit.cpp \ widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp \ - widgets/HelpTextWindow.cpp widgets/RestrictedSpinBox.cpp + widgets/HelpTextWindow.cpp widgets/RestrictedSpinBox.cpp \ + widgets/LazyFillComboBox.cpp widgets/CheckableItemComboBox.cpp + HEADERS += \ widgets/mainwindow.h widgets/plotter.h \ widgets/about.h widgets/widegraph.h \ @@ -22,7 +24,8 @@ HEADERS += \ widgets/ExportCabrillo.h widgets/AbstractLogWindow.hpp \ widgets/FoxLogWindow.hpp widgets/CabrilloLogWindow.hpp \ widgets/DateTimeEdit.hpp widgets/HelpTextWindow.hpp \ - widgets/RestrictedSpinBox.hpp + widgets/RestrictedSpinBox.hpp \ + widgets/LazyFillComboBox.hpp widgets/CheckableItemComboBox.hpp FORMS += \ widgets/mainwindow.ui widgets/about.ui \ From 1d9dd7df24a6b452de757257211ac26ac3ebf38e Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 20:29:25 +0000 Subject: [PATCH 57/73] Remove unwanted file and directory --- lib/fsk4hf/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 lib/fsk4hf/.DS_Store diff --git a/lib/fsk4hf/.DS_Store b/lib/fsk4hf/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Tue, 3 Nov 2020 20:31:11 +0000 Subject: [PATCH 58/73] Add network interface selection combo box widget to message_aggregator --- CMakeLists.txt | 2 +- UDPExamples/MessageAggregatorMainWindow.cpp | 96 ++++++++++++++++++--- UDPExamples/MessageAggregatorMainWindow.hpp | 7 ++ UDPExamples/MessageServer.cpp | 10 ++- UDPExamples/MessageServer.hpp | 4 +- UDPExamples/UDPDaemon.cpp | 2 +- 6 files changed, 101 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b07684e9..d9ff2be75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1491,7 +1491,7 @@ add_executable (message_aggregator ${message_aggregator_RESOURCES_RCC} ${message_aggregator_VERSION_RESOURCES} ) -target_link_libraries (message_aggregator Qt5::Widgets wsjtx_udp-static) +target_link_libraries (message_aggregator wsjt_qt Qt5::Widgets wsjtx_udp-static) if (WSJT_CREATE_WINMAIN) set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON) diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index 7e74342c0..d110bfc44 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include "DecodesModel.hpp" #include "BeaconsModel.hpp" @@ -37,8 +39,10 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () , decodes_model_ {new DecodesModel {this}} , beacons_model_ {new BeaconsModel {this}} , server_ {new MessageServer {this}} - , multicast_group_line_edit_ {new QLineEdit} - , log_table_view_ {new QTableView} + , port_spin_box_ {new QSpinBox {this}} + , multicast_group_line_edit_ {new QLineEdit {this}} + , network_interfaces_combo_box_ {new CheckableItemComboBox {this}} + , log_table_view_ {new QTableView {this}} , add_call_of_interest_action_ {new QAction {tr ("&Add callsign"), this}} , delete_call_of_interest_action_ {new QAction {tr ("&Delete callsign"), this}} , last_call_of_interest_action_ {new QAction {tr ("&Highlight last only"), this}} @@ -68,16 +72,66 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () auto central_layout = new QVBoxLayout; // server details - auto port_spin_box = new QSpinBox; - port_spin_box->setMinimum (1); - port_spin_box->setMaximum (std::numeric_limits::max ()); + port_spin_box_->setMinimum (1); + port_spin_box_->setMaximum (std::numeric_limits::max ()); auto group_box_layout = new QFormLayout; - group_box_layout->addRow (tr ("Port number:"), port_spin_box); + group_box_layout->addRow (tr ("Port number:"), port_spin_box_); group_box_layout->addRow (tr ("Multicast Group (blank for unicast server):"), multicast_group_line_edit_); + group_box_layout->addRow (tr ("Network interfaces:"), network_interfaces_combo_box_); + int row; + QFormLayout::ItemRole role; + group_box_layout->getWidgetPosition (network_interfaces_combo_box_, &row, &role); + Q_ASSERT (row >= 0); + network_interfaces_form_label_widget_ = static_cast (group_box_layout->itemAt (row, QFormLayout::LabelRole)->widget ()); + network_interfaces_form_label_widget_->hide (); + network_interfaces_form_label_widget_->buddy ()->hide (); + connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this] { + if (multicast_group_line_edit_->text ().size ()) + { + network_interfaces_form_label_widget_->show (); + network_interfaces_form_label_widget_->buddy ()->show (); + } + else + { + network_interfaces_form_label_widget_->hide (); + network_interfaces_form_label_widget_->buddy ()->hide (); + } + }); auto group_box = new QGroupBox {tr ("Server Details")}; group_box->setLayout (group_box_layout); central_layout->addWidget (group_box); + // populate network interface list + for (auto const& net_if : QNetworkInterface::allInterfaces ()) + { + auto flags = QNetworkInterface::IsRunning | QNetworkInterface::CanMulticast; + if ((net_if.flags () & flags) == flags) + { + auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + auto item = network_interfaces_combo_box_->addCheckItem (net_if.humanReadableName () + , net_if.name () + , is_loopback ? Qt::Checked : Qt::Unchecked); + item->setEnabled (!is_loopback); + auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) + .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); + auto hw_addr = net_if.hardwareAddress (); + if (hw_addr.size ()) + { + tip += QString {"\nhw: %1"}.arg (net_if.hardwareAddress ()); + } + auto aes = net_if.addressEntries (); + if (aes.size ()) + { + tip += "\naddresses:"; + for (auto const& ae : aes) + { + tip += QString {"\n ip: %1/%2"}.arg (ae.ip ().toString ()).arg (ae.prefixLength ()); + } + } + item->setToolTip (tip); + } + } + log_table_view_->setModel (log_); log_table_view_->verticalHeader ()->hide (); central_layout->addWidget (log_table_view_); @@ -200,16 +254,34 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () connect (decodes_model_, &DecodesModel::reply, server_, &MessageServer::reply); // UI behaviour - connect (port_spin_box, static_cast (&QSpinBox::valueChanged) - , [this] (port_type port) {server_->start (port);}); - connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this, port_spin_box] () { - server_->start (port_spin_box->value (), QHostAddress {multicast_group_line_edit_->text ()}); - }); + connect (port_spin_box_, static_cast (&QSpinBox::valueChanged) + , [this] (int /*port*/) {restart_server ();}); + connect (multicast_group_line_edit_, &QLineEdit::editingFinished, [this] () {restart_server ();}); + connect (network_interfaces_combo_box_, &QComboBox::currentTextChanged, [this] () {restart_server ();}); - port_spin_box->setValue (2237); // start up in unicast mode + port_spin_box_->setValue (2237); // start up in unicast mode show (); } +void MessageAggregatorMainWindow::restart_server () +{ + QSet net_ifs; + if (network_interfaces_combo_box_->isVisible ()) + { + auto model = static_cast (network_interfaces_combo_box_->model ()); + for (int row = 0; row < model->rowCount (); ++row) + { + if (Qt::Checked == model->item (row)->checkState ()) + { + net_ifs << model->item (row)->data ().toString (); + } + } + } + server_->start (port_spin_box_->value () + , QHostAddress {multicast_group_line_edit_->text ()} + , net_ifs); +} + void MessageAggregatorMainWindow::log_qso (ClientKey const& /*key*/, QDateTime time_off , QString const& dx_call , QString const& dx_grid, Frequency dial_frequency, QString const& mode diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 445a5908e..1bff0d692 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -6,6 +6,7 @@ #include #include "MessageServer.hpp" +#include "widgets/CheckableItemComboBox.hpp" class QDateTime; class QStandardItemModel; @@ -16,6 +17,8 @@ class QLineEdit; class QTableView; class ClientWidget; class QListWidget; +class QLabel; +class QSpinBox; using Frequency = MessageServer::Frequency; @@ -38,6 +41,7 @@ public: , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); private: + void restart_server (); void add_client (ClientKey const&, QString const& version, QString const& revision); void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, @@ -52,7 +56,10 @@ private: DecodesModel * decodes_model_; BeaconsModel * beacons_model_; MessageServer * server_; + QSpinBox * port_spin_box_; QLineEdit * multicast_group_line_edit_; + CheckableItemComboBox * network_interfaces_combo_box_; + QLabel * network_interfaces_form_label_widget_; QTableView * log_table_view_; QListWidget * calls_of_interest_; QAction * add_call_of_interest_action_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 8869c4b89..6745fe0a7 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -78,7 +77,7 @@ public: QString version_; QString revision_; QHostAddress multicast_group_address_; - QStringList network_interfaces_; + QSet network_interfaces_; static BindMode constexpr bind_mode_ = ShareAddress | ReuseAddressHint; struct Client { @@ -433,9 +432,12 @@ MessageServer::MessageServer (QObject * parent, QString const& version, QString } void MessageServer::start (port_type port, QHostAddress const& multicast_group_address - , QStringList const& network_interface_names) + , QSet const& network_interface_names) { - if (port != m_->localPort () || multicast_group_address != m_->multicast_group_address_) + qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names; + if (port != m_->localPort () + || multicast_group_address != m_->multicast_group_address_ + || network_interface_names != m_->network_interfaces_) { m_->leave_multicast_group (); if (impl::UnconnectedState != m_->state ()) diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 8a31e7bd5..7cf5653a0 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -44,7 +44,7 @@ public: // which the server will join Q_SLOT void start (port_type port , QHostAddress const& multicast_group_address = QHostAddress {} - , QStringList const& network_interface_names = QStringList {}); + , QSet const& network_interface_names = QSet {}); // ask the client to clear one or both of the decode windows Q_SLOT void clear_decodes (ClientKey const&, quint8 window = 0); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2044bfb00..0f6793028 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -169,7 +169,7 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); - server_->start (port, multicast_group, network_interface_names); + server_->start (port, multicast_group, QSet {network_interface_names.begin (), network_interface_names.end ()}); } private: From ff6f01c6b5126be90d56f368de9e7b3d77820f8b Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:07:38 +0000 Subject: [PATCH 59/73] Pre Qt v5.11 compatibility --- qt_helpers.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/qt_helpers.hpp b/qt_helpers.hpp index 7170bda0b..034a8852f 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -117,6 +117,16 @@ namespace std } #endif +inline +bool is_broadcast_address (QHostAddress const& host_addr) +{ +#if QT_VERSION >= 0x051100 + return host_addr.isBroadcast (); +#else + bool ok; + return host_addr.toIPv4Address (&ok) == 0xffffffffu && ok; +#endif +} inline bool is_multicast_address (QHostAddress const& host_addr) From e538ce9294d57508655136b2c09632025f7e247c Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:08:12 +0000 Subject: [PATCH 60/73] Disallow sending UDP Message Protocol traffic to broadcast address --- Network/MessageClient.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 57ffb2806..3474f19bb 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -148,6 +148,13 @@ void MessageClient::impl::start () return; } + if (is_broadcast_address (server_)) + { + Q_EMIT self_->error ("IPv4 broadcast not supported, please specify the loop-back address, a server host address, or multicast group address"); + pending_messages_.clear (); // discard + return; + } + if (blocked_addresses_.end () != std::find (blocked_addresses_.begin (), blocked_addresses_.end (), server_)) { Q_EMIT self_->error ("UDP server blocked, please try another"); @@ -181,13 +188,6 @@ void MessageClient::impl::start () } } - if (server_.isBroadcast ()) - { - // only allow broadcast on the loopback interface to avoid - // flooding the local subnet which may be large with some ISPs - //interface_ip.setAddress ("127.0.0.1"); - } - if (localAddress () != interface_ip) { if (UnconnectedState != state () || state ()) From 50cce43e927d47fb8e318dff0006c2a7a38100c3 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:14:26 +0000 Subject: [PATCH 61/73] Pre Qt 5.14 compatibility --- UDPExamples/UDPDaemon.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 0f6793028..6d98b3a6b 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -169,7 +169,11 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); +#if QT_VERSION >= 0x051400 server_->start (port, multicast_group, QSet {network_interface_names.begin (), network_interface_names.end ()}); +#else + server_->start (port, multicast_group, network_interface_names.toSet ()); +#endif } private: From f4db2904a3191a53e2f1342df2a7440d2b7cbb4d Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Tue, 3 Nov 2020 23:44:07 +0000 Subject: [PATCH 62/73] Correct Qt version checks --- Network/NetworkMessage.cpp | 8 ++++---- Network/NetworkMessage.hpp | 4 ++-- UDPExamples/UDPDaemon.cpp | 2 +- qt_helpers.hpp | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Network/NetworkMessage.cpp b/Network/NetworkMessage.cpp index 5af133c7f..a1e7050f2 100644 --- a/Network/NetworkMessage.cpp +++ b/Network/NetworkMessage.cpp @@ -28,13 +28,13 @@ namespace NetworkMessage { setVersion (QDataStream::Qt_5_0); // Qt schema version } -#if QT_VERSION >= 0x050200 +#if QT_VERSION >= QT_VERSION_CHECK (5, 2, 0) else if (schema <= 2) { setVersion (QDataStream::Qt_5_2); // Qt schema version } #endif -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 4, 0) else if (schema <= 3) { setVersion (QDataStream::Qt_5_4); // Qt schema version @@ -73,13 +73,13 @@ namespace NetworkMessage { parent->setVersion (QDataStream::Qt_5_0); } -#if QT_VERSION >= 0x050200 +#if QT_VERSION >= QT_VERSION_CHECK (5, 2, 0) else if (schema_ <= 2) { parent->setVersion (QDataStream::Qt_5_2); } #endif -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 4, 0) else if (schema_ <= 3) { parent->setVersion (QDataStream::Qt_5_4); diff --git a/Network/NetworkMessage.hpp b/Network/NetworkMessage.hpp index c484efb23..f892eda06 100644 --- a/Network/NetworkMessage.hpp +++ b/Network/NetworkMessage.hpp @@ -540,9 +540,9 @@ namespace NetworkMessage // increment this if a newer Qt schema is required and add decode // logic to the Builder and Reader class implementations -#if QT_VERSION >= 0x050400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 4, 0) static quint32 constexpr schema_number {3}; -#elif QT_VERSION >= 0x050200 +#elif QT_VERSION >= QT_VERSION_CHECK (5, 2, 0) static quint32 constexpr schema_number {2}; #else // Schema 1 (Qt_5_0) is broken diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 6d98b3a6b..78d1a0c52 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -169,7 +169,7 @@ public: connect (server_, &MessageServer::client_opened, this, &Server::add_client); connect (server_, &MessageServer::client_closed, this, &Server::remove_client); -#if QT_VERSION >= 0x051400 +#if QT_VERSION >= QT_VERSION_CHECK (5, 14, 0) server_->start (port, multicast_group, QSet {network_interface_names.begin (), network_interface_names.end ()}); #else server_->start (port, multicast_group, network_interface_names.toSet ()); diff --git a/qt_helpers.hpp b/qt_helpers.hpp index 034a8852f..416b6421b 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -120,7 +120,7 @@ namespace std inline bool is_broadcast_address (QHostAddress const& host_addr) { -#if QT_VERSION >= 0x051100 +#if QT_VERSION >= QT_VERSION_CHECK (5, 11, 0) return host_addr.isBroadcast (); #else bool ok; @@ -131,7 +131,7 @@ bool is_broadcast_address (QHostAddress const& host_addr) inline bool is_multicast_address (QHostAddress const& host_addr) { -#if QT_VERSION >= 0x050600 +#if QT_VERSION >= QT_VERSION_CHECK (5, 6, 0) return host_addr.isMulticast (); #else bool ok; From e61a1f969c8b0e21d611412cdf2f9e388333a323 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 4 Nov 2020 16:02:04 +0000 Subject: [PATCH 63/73] UDP multicast TTL default as one Restricts scope to local subnet. --- Configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration.cpp b/Configuration.cpp index fac5564ab..78f3dafa6 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -1546,7 +1546,7 @@ void Configuration::impl::read_settings () opCall_ = settings_->value ("OpCall", "").toString (); udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString (); udp_interface_name_ = settings_->value ("UDPInterface").toString (); - udp_TTL_ = settings_->value ("UDPTTL").toInt (); + udp_TTL_ = settings_->value ("UDPTTL", 1).toInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString (); n1mm_server_port_ = settings_->value ("N1MMServerPort", 2333).toUInt (); From 780b1f74ee0251392d242ee5d1fcb4ef92d58fd7 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 5 Nov 2020 03:37:01 +0000 Subject: [PATCH 64/73] Message Client allows sending multicast UDP on multiple interfaces --- Configuration.cpp | 87 ++++++++++++------- Configuration.hpp | 6 +- Configuration.ui | 21 +++-- Network/MessageClient.cpp | 92 ++++++++------------- Network/MessageClient.hpp | 4 +- UDPExamples/MessageAggregatorMainWindow.cpp | 22 ++--- UDPExamples/UDPDaemon.cpp | 30 +++---- widgets/CheckableItemComboBox.cpp | 2 +- widgets/CheckableItemComboBox.hpp | 5 +- widgets/LazyFillComboBox.hpp | 2 +- widgets/mainwindow.cpp | 4 +- 11 files changed, 145 insertions(+), 130 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 78f3dafa6..7f68bb417 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -166,6 +166,7 @@ #include #include #include +#include #include #include "pimpl_impl.hpp" @@ -442,7 +443,8 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); - void load_network_interfaces (QComboBox *, QString const& current); + void load_network_interfaces (CheckableItemComboBox *, QStringList const& current); + QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -653,7 +655,7 @@ private: bool udp_server_name_edited_; int dns_lookup_id_; port_type udp_server_port_; - QString udp_interface_name_; + QStringList udp_interface_names_; int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; @@ -754,7 +756,7 @@ QString Configuration::opCall() const {return m_->opCall_;} void Configuration::opCall (QString const& call) {m_->opCall_ = call;} QString Configuration::udp_server_name () const {return m_->udp_server_name_;} auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;} -QString Configuration::udp_interface_name () const {return m_->udp_interface_name_;} +QStringList Configuration::udp_interface_names () const {return m_->udp_interface_names_;} int Configuration::udp_TTL () const {return m_->udp_TTL_;} bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;} QString Configuration::n1mm_server_name () const {return m_->n1mm_server_name_;} @@ -1078,9 +1080,9 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network }); // set up dynamic loading of network interfaces - connect (ui_->udp_interface_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { + connect (ui_->udp_interfaces_combo_box, &LazyFillComboBox::about_to_show_popup, [this] () { QGuiApplication::setOverrideCursor (QCursor {Qt::WaitCursor}); - load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); + load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); @@ -1362,10 +1364,10 @@ void Configuration::impl::initialize_models () ui_->udp_server_line_edit->setText (udp_server_name_); on_udp_server_line_edit_editingFinished (); ui_->udp_server_port_spin_box->setValue (udp_server_port_); - load_network_interfaces (ui_->udp_interface_combo_box, udp_interface_name_); - if (!udp_interface_name_.size ()) + load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); + if (!udp_interface_names_.size ()) { - udp_interface_name_ = ui_->udp_interface_combo_box->currentData ().toString (); + udp_interface_names_ = get_selected_network_interfaces (ui_->udp_interfaces_combo_box); } ui_->udp_TTL_spin_box->setValue (udp_TTL_); ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_); @@ -1545,7 +1547,7 @@ void Configuration::impl::read_settings () rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value (); opCall_ = settings_->value ("OpCall", "").toString (); udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString (); - udp_interface_name_ = settings_->value ("UDPInterface").toString (); + udp_interface_names_ = settings_->value ("UDPInterface").toStringList (); udp_TTL_ = settings_->value ("UDPTTL", 1).toInt (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); n1mm_server_name_ = settings_->value ("N1MMServer", "127.0.0.1").toString (); @@ -1675,7 +1677,7 @@ void Configuration::impl::write_settings () settings_->setValue ("OpCall", opCall_); settings_->setValue ("UDPServer", udp_server_name_); settings_->setValue ("UDPServerPort", udp_server_port_); - settings_->setValue ("UDPInterface", udp_interface_name_); + settings_->setValue ("UDPInterface", QVariant::fromValue (udp_interface_names_)); settings_->setValue ("UDPTTL", udp_TTL_); settings_->setValue ("N1MMServer", n1mm_server_name_); settings_->setValue ("N1MMServerPort", n1mm_server_port_); @@ -2105,12 +2107,12 @@ void Configuration::impl::accept () opCall_=ui_->opCallEntry->text(); auto new_server = ui_->udp_server_line_edit->text ().trimmed (); - auto new_interface = ui_->udp_interface_combo_box->currentData ().toString (); - if (new_server != udp_server_name_ || new_interface != udp_interface_name_) + auto new_interfaces = get_selected_network_interfaces (ui_->udp_interfaces_combo_box); + if (new_server != udp_server_name_ || new_interfaces != udp_interface_names_) { udp_server_name_ = new_server; - udp_interface_name_ = new_interface; - Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_name_); + udp_interface_names_ = new_interfaces; + Q_EMIT self_->udp_server_changed (udp_server_name_, udp_interface_names_); } auto new_port = ui_->udp_server_port_spin_box->value (); @@ -2452,8 +2454,8 @@ void Configuration::impl::host_info_results (QHostInfo host_info) void Configuration::impl::check_multicast (QHostAddress const& ha) { auto is_multicast = is_multicast_address (ha); - ui_->udp_interface_label->setVisible (is_multicast); - ui_->udp_interface_combo_box->setVisible (is_multicast); + ui_->udp_interfaces_label->setVisible (is_multicast); + ui_->udp_interfaces_combo_box->setVisible (is_multicast); ui_->udp_TTL_label->setVisible (is_multicast); ui_->udp_TTL_spin_box->setVisible (is_multicast); if (isVisible ()) @@ -2993,28 +2995,53 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com } // load the available network interfaces into the selection combo box -void Configuration::impl::load_network_interfaces (QComboBox * combo_box, QString const& current) +void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList const& current) { combo_box->clear (); - int current_index = -1; - for (auto const& interface : QNetworkInterface::allInterfaces ()) + for (auto const& net_if : QNetworkInterface::allInterfaces ()) { - if (interface.flags () & QNetworkInterface::IsUp) + auto flags = QNetworkInterface::IsUp | QNetworkInterface::CanMulticast; + if ((net_if.flags () & flags) == flags) { - auto const& name = interface.name (); - combo_box->addItem (interface.humanReadableName (), name); - // select the first loopback interface as a default to - // discourage spamming the network (possibly the Internet), - // particularly important with administratively scoped - // multicast UDP - if (name == current - || (!current.size () && (interface.flags () & QNetworkInterface::IsLoopBack))) + auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + auto item = combo_box->addCheckItem (net_if.humanReadableName () + , net_if.name () + , is_loopback || current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); + item->setEnabled (!is_loopback); + auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) + .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); + auto hw_addr = net_if.hardwareAddress (); + if (hw_addr.size ()) { - current_index = combo_box->count () - 1; + tip += QString {"\nhw: %1"}.arg (net_if.hardwareAddress ()); } + auto aes = net_if.addressEntries (); + if (aes.size ()) + { + tip += "\naddresses:"; + for (auto const& ae : aes) + { + tip += QString {"\n ip: %1/%2"}.arg (ae.ip ().toString ()).arg (ae.prefixLength ()); + } + } + item->setToolTip (tip); } } - combo_box->setCurrentIndex (current_index); +} + +// get the select network interfaces from the selection combo box +QStringList Configuration::impl::get_selected_network_interfaces (CheckableItemComboBox * combo_box) +{ + QStringList interfaces; + auto model = static_cast (combo_box->model ()); + for (int row = 0; row < model->rowCount (); ++row) + { + if (Qt::Checked == model->item (row)->checkState ()) + { + interfaces << model->item (row)->data ().toString (); + } + } + return interfaces; } // enable only the channels that are supported by the selected audio device diff --git a/Configuration.hpp b/Configuration.hpp index 403673663..b0f6bf75b 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "Radio.hpp" #include "models/IARURegions.hpp" @@ -14,7 +15,6 @@ class QSettings; class QWidget; class QAudioDeviceInfo; -class QString; class QDir; class QNetworkAccessManager; class Bands; @@ -151,7 +151,7 @@ public: void opCall (QString const&); QString udp_server_name () const; port_type udp_server_port () const; - QString udp_interface_name () const; + QStringList udp_interface_names () const; int udp_TTL () const; QString n1mm_server_name () const; port_type n1mm_server_port () const; @@ -274,7 +274,7 @@ public: // // This signal is emitted when the UDP server changes // - Q_SIGNAL void udp_server_changed (QString& udp_server_name, QString const& network_interface) const; + Q_SIGNAL void udp_server_changed (QString& udp_server_name, QStringList const& network_interfaces) const; Q_SIGNAL void udp_server_port_changed (port_type server_port) const; Q_SIGNAL void udp_TTL_changed (int TTL) const; Q_SIGNAL void accept_udp_requests_changed (bool checked) const; diff --git a/Configuration.ui b/Configuration.ui index fd8fb8955..1b6ef8926 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -1893,17 +1893,17 @@ and DX Grid fields when a 73 or free text message is sent. - + - Outgoing interface: + Outgoing interfaces: - udp_interface_combo_box + udp_interfaces_combo_box - + @@ -3029,6 +3029,11 @@ Right click for insert and delete options. QComboBox
widgets/LazyFillComboBox.hpp
+ + CheckableItemComboBox + QComboBox +
widgets/CheckableItemComboBox.hpp
+
configuration_tabs @@ -3111,7 +3116,7 @@ Right click for insert and delete options. psk_reporter_tcpip_check_box udp_server_line_edit udp_server_port_spin_box - udp_interface_combo_box + udp_interfaces_combo_box udp_TTL_spin_box accept_udp_requests_check_box udpWindowToFront @@ -3221,13 +3226,13 @@ Right click for insert and delete options. - + - + - + diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 3474f19bb..2e721d5f7 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -59,7 +59,7 @@ public: enum StreamStatus {Fail, Short, OK}; - void set_server (QString const& server_name, QString const& network_interface_name); + void set_server (QString const& server_name, QStringList const& network_interface_names); Q_SLOT void host_info_results (QHostInfo); void start (); void parse_message (QByteArray const&); @@ -67,12 +67,12 @@ public: void heartbeat (); void closedown (); StreamStatus check_status (QDataStream const&) const; - void send_message (QByteArray const&); - void send_message (QDataStream const& out, QByteArray const& message) + void send_message (QByteArray const&, bool queue_if_pending = true); + void send_message (QDataStream const& out, QByteArray const& message, bool queue_if_pending = true) { if (OK == check_status (out)) { - send_message (message); + send_message (message, queue_if_pending); } else { @@ -89,7 +89,7 @@ public: QHostAddress server_; port_type server_port_; int TTL_; - QNetworkInterface network_interface_; + std::vector network_interfaces_; quint32 schema_; QTimer * heartbeat_timer_; std::vector blocked_addresses_; @@ -101,10 +101,15 @@ public: #include "MessageClient.moc" -void MessageClient::impl::set_server (QString const& server_name, QString const& network_interface_name) +void MessageClient::impl::set_server (QString const& server_name, QStringList const& network_interface_names) { server_.setAddress (server_name); - network_interface_ = QNetworkInterface::interfaceFromName (network_interface_name); + network_interfaces_.clear (); + for (auto const& net_if_name : network_interface_names) + { + network_interfaces_.push_back (QNetworkInterface::interfaceFromName (net_if_name)); + } + if (server_.isNull () && server_name.size ()) // DNS lookup required { // queue a host address lookup @@ -162,33 +167,10 @@ void MessageClient::impl::start () return; } - TRACE_UDP ("Trying server:" << server_.toString () << "on interface:" << network_interface_.humanReadableName ()); - QHostAddress interface_ip {QHostAddress::Any}; - if (network_interface_.isValid ()) - { - if (is_multicast_address (server_) && !(network_interface_.flags () & QNetworkInterface::CanMulticast)) - { - Q_EMIT self_->error ("Network interface is not multicast capable, please try another"); - return; - } - for (auto const& ae : network_interface_.addressEntries ()) - { - auto const& ip = ae.ip (); - if (server_.protocol () == ip.protocol ()) - { - interface_ip = ip; - break; - } - } - if (QHostAddress {QHostAddress::Any} == interface_ip) - { - Q_EMIT self_->error ("Network interface has no suitable address for server IP protocol, please try another"); - pending_messages_.clear (); // discard - return; - } - } + TRACE_UDP ("Trying server:" << server_.toString ()); + QHostAddress interface_addr {IPv6Protocol == server_.protocol () ? QHostAddress::AnyIPv6 : QHostAddress::AnyIPv4}; - if (localAddress () != interface_ip) + if (localAddress () != interface_addr) { if (UnconnectedState != state () || state ()) { @@ -196,8 +178,8 @@ void MessageClient::impl::start () } // bind to an ephemeral port on the selected interface and set // up for sending datagrams - bind (interface_ip); - setMulticastInterface (network_interface_); + bind (interface_addr); + qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress (); // set multicast TTL to limit scope when sending to multicast // group addresses @@ -210,7 +192,7 @@ void MessageClient::impl::start () // clear any backlog while (pending_messages_.size ()) { - send_message (pending_messages_.dequeue ()); + send_message (pending_messages_.dequeue (), false); } } @@ -438,14 +420,11 @@ void MessageClient::impl::heartbeat () if (server_port_ && !server_.isNull ()) { QByteArray message; - NetworkMessage::Builder hb {&message, NetworkMessage::Heartbeat, id_, schema_}; - hb << NetworkMessage::Builder::schema_number // maximum schema number accepted - << version_.toUtf8 () << revision_.toUtf8 (); - if (OK == check_status (hb)) - { - TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_); - writeDatagram (message, server_, server_port_); - } + NetworkMessage::Builder out {&message, NetworkMessage::Heartbeat, id_, schema_}; + out << NetworkMessage::Builder::schema_number // maximum schema number accepted + << version_.toUtf8 () << revision_.toUtf8 (); + TRACE_UDP ("schema:" << schema_ << "max schema:" << NetworkMessage::Builder::schema_number << "version:" << version_ << "revision:" << revision_); + send_message (out, message, false); } } @@ -455,15 +434,12 @@ void MessageClient::impl::closedown () { QByteArray message; NetworkMessage::Builder out {&message, NetworkMessage::Close, id_, schema_}; - if (OK == check_status (out)) - { - TRACE_UDP (""); - writeDatagram (message, server_, server_port_); - } + TRACE_UDP (""); + send_message (out, message, false); } } -void MessageClient::impl::send_message (QByteArray const& message) +void MessageClient::impl::send_message (QByteArray const& message, bool queue_if_pending) { if (server_port_) { @@ -471,11 +447,15 @@ void MessageClient::impl::send_message (QByteArray const& message) { if (message != last_message_) // avoid duplicates { - writeDatagram (message, server_, server_port_); + for (auto const& net_if : network_interfaces_) + { + setMulticastInterface (net_if); + writeDatagram (message, server_, server_port_); + } last_message_ = message; } } - else + else if (queue_if_pending) { pending_messages_.enqueue (message); } @@ -509,7 +489,7 @@ auto MessageClient::impl::check_status (QDataStream const& stream) const -> Stre MessageClient::MessageClient (QString const& id, QString const& version, QString const& revision, QString const& server_name, port_type server_port, - QString const& network_interface_name, + QStringList const& network_interface_names, int TTL, QObject * self) : QObject {self} , m_ {id, version, revision, server_port, TTL, this} @@ -532,7 +512,7 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString Q_EMIT error (m_->errorString ()); } }); - m_->set_server (server_name, network_interface_name); + m_->set_server (server_name, network_interface_names); } QHostAddress MessageClient::server_address () const @@ -545,9 +525,9 @@ auto MessageClient::server_port () const -> port_type return m_->server_port_; } -void MessageClient::set_server (QString const& server_name, QString const& network_interface_name) +void MessageClient::set_server (QString const& server_name, QStringList const& network_interface_names) { - m_->set_server (server_name, network_interface_name); + m_->set_server (server_name, network_interface_names); } void MessageClient::set_server_port (port_type server_port) diff --git a/Network/MessageClient.hpp b/Network/MessageClient.hpp index d0066dbe4..cc348be2d 100644 --- a/Network/MessageClient.hpp +++ b/Network/MessageClient.hpp @@ -36,7 +36,7 @@ public: // messages will be silently dropped until a server host lookup is complete MessageClient (QString const& id, QString const& version, QString const& revision, QString const& server_name, port_type server_port, - QString const& network_interface_name, + QStringList const& network_interface_names, int TTL, QObject * parent = nullptr); // query server details @@ -46,7 +46,7 @@ public: // initiate a new server host lookup or if the server name is empty // the sending of messages is disabled, if an interface is specified // then that interface is used for outgoing datagrams - Q_SLOT void set_server (QString const& server_name, QString const& network_interface_name); + Q_SLOT void set_server (QString const& server_name, QStringList const& network_interface_names); // change the server port messages are sent to Q_SLOT void set_server_port (port_type server_port = 0u); diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index d110bfc44..a0fe90c47 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -266,17 +266,17 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () void MessageAggregatorMainWindow::restart_server () { QSet net_ifs; - if (network_interfaces_combo_box_->isVisible ()) - { - auto model = static_cast (network_interfaces_combo_box_->model ()); - for (int row = 0; row < model->rowCount (); ++row) - { - if (Qt::Checked == model->item (row)->checkState ()) - { - net_ifs << model->item (row)->data ().toString (); - } - } - } + if (network_interfaces_combo_box_->isVisible ()) + { + auto model = static_cast (network_interfaces_combo_box_->model ()); + for (int row = 0; row < model->rowCount (); ++row) + { + if (Qt::Checked == model->item (row)->checkState ()) + { + net_ifs << model->item (row)->data ().toString (); + } + } + } server_->start (port_spin_box_->value () , QHostAddress {multicast_group_line_edit_->text ()} , net_ifs); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 78d1a0c52..2d028f074 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -65,14 +65,14 @@ public: { if (f != dial_frequency_) { - std::cout << tr ("%1(%2): Dial frequency changed to %3") - .arg (key_.second).arg (key_.first.toString ()).arg (f).toStdString () << std::endl; + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Dial frequency changed to %1"}.arg (f).toStdString () << std::endl; dial_frequency_ = f; } if (mode + sub_mode != mode_) { - std::cout << tr ("%1(%2): Mode changed to %3") - .arg (key_.second).arg (key_.first.toString ()).arg (mode + sub_mode).toStdString () << std::endl; + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Mode changed to %1"}.arg (mode + sub_mode).toStdString () << std::endl; mode_ = mode + sub_mode; } } @@ -88,8 +88,8 @@ public: << "Dt:" << delta_time << "Df:" << delta_frequency << "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high") << "On air:" << !off_air; - std::cout << tr ("%1(%2): Decoded %3") - .arg (key_.second).arg (key_.first.toString ()).arg (message).toStdString () << std::endl; + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Decoded %1"}.arg (message).toStdString () << std::endl; } } @@ -102,8 +102,9 @@ public: qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "drift:" << drift; - std::cout << tr ("%1(%2): WSPR decode %3 grid %4 power: %5") - .arg (key_.second).arg (key_.first.toString ()).arg (callsign).arg (grid).arg (power).toStdString () + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"WSPR decode %1 grid %2 power: %3"} + .arg (callsign).arg (grid).arg (power).toStdString () << "On air:" << !off_air << std::endl; } } @@ -125,12 +126,13 @@ public: << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent << "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode; std::cout << QByteArray {80, '-'}.data () << '\n'; - std::cout << tr ("%1(%2): Logged %3 grid: %4 power: %5 sent: %6 recd: %7 freq: %8 time_off: %9 op: %10 my_call: %11 my_grid: %12 exchange_sent: %13 exchange_rcvd: %14 comments: %15 prop_mode: %16") - .arg (key_.second).arg (key.first.toString ()).arg (dx_call).arg (dx_grid).arg (tx_power) - .arg (report_sent).arg (report_received) - .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) - .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) - .arg (comments).arg (prop_mode).toStdString () + std::cout << QString {"%1(%2): "}.arg (key_.second).arg (key_.first.toString ()).toStdString () + << QString {"Logged %1 grid: %2 power: %3 sent: %4 recd: %5 freq: %6 time_off: %7 op: %8 my_call: %9 my_grid: %10 exchange_sent: %11 exchange_rcvd: %12 comments: %13 prop_mode: %14"} + .arg (dx_call).arg (dx_grid).arg (tx_power) + .arg (report_sent).arg (report_received) + .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) + .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) + .arg (comments).arg (prop_mode).toStdString () << std::endl; } } diff --git a/widgets/CheckableItemComboBox.cpp b/widgets/CheckableItemComboBox.cpp index 3ef926243..13115c993 100644 --- a/widgets/CheckableItemComboBox.cpp +++ b/widgets/CheckableItemComboBox.cpp @@ -25,7 +25,7 @@ public: }; CheckableItemComboBox::CheckableItemComboBox (QWidget * parent) - : QComboBox {parent} + : LazyFillComboBox {parent} , model_ {new QStandardItemModel()} { setModel (model_.data ()); diff --git a/widgets/CheckableItemComboBox.hpp b/widgets/CheckableItemComboBox.hpp index 2aa3e9831..21e751167 100644 --- a/widgets/CheckableItemComboBox.hpp +++ b/widgets/CheckableItemComboBox.hpp @@ -1,9 +1,10 @@ #ifndef CHECKABLE_ITEM_COMBO_BOX_HPP__ #define CHECKABLE_ITEM_COMBO_BOX_HPP__ -#include #include +#include "LazyFillComboBox.hpp" + class QStandardItemModel; class QStandardItem; @@ -12,7 +13,7 @@ class QStandardItem; * http://stackoverflow.com/questions/8422760/combobox-of-checkboxes */ class CheckableItemComboBox - : public QComboBox + : public LazyFillComboBox { Q_OBJECT diff --git a/widgets/LazyFillComboBox.hpp b/widgets/LazyFillComboBox.hpp index 37af60f0b..7ac828fed 100644 --- a/widgets/LazyFillComboBox.hpp +++ b/widgets/LazyFillComboBox.hpp @@ -10,7 +10,7 @@ class QWidget; // // QComboBox derivative that signals show and hide of the pop up list. // -class LazyFillComboBox final +class LazyFillComboBox : public QComboBox { Q_OBJECT diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index e40009cb4..2a649b4a2 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -417,7 +417,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, m_messageClient {new MessageClient {QApplication::applicationName (), version (), revision (), m_config.udp_server_name (), m_config.udp_server_port (), - m_config.udp_interface_name (), m_config.udp_TTL (), + m_config.udp_interface_names (), m_config.udp_TTL (), this}}, m_psk_Reporter {&m_config, QString {"WSJT-X v" + version () + " " + m_revision}.simplified ()}, m_manual {&m_network_manager}, @@ -7837,7 +7837,7 @@ void MainWindow::networkError (QString const& e) , MessageBox::Cancel)) { // retry server lookup - m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_name ()); + m_messageClient->set_server (m_config.udp_server_name (), m_config.udp_interface_names ()); } } From bdaf51a0741db853ce753467cc7381e069a020a4 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 5 Nov 2020 11:30:48 +0000 Subject: [PATCH 65/73] Comment out diagnostic prints --- Configuration.cpp | 4 ++-- Network/MessageClient.cpp | 2 +- UDPExamples/MessageServer.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 7f68bb417..a13dc2723 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -2418,7 +2418,7 @@ void Configuration::impl::on_udp_server_line_edit_editingFinished () if (server.size () && ha.isNull ()) { // queue a host address lookup - qDebug () << "server host DNS lookup:" << server; + // qDebug () << "server host DNS lookup:" << server; #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) dns_lookup_id_ = QHostInfo::lookupHost (server, this, &Configuration::impl::host_info_results); #else @@ -2443,7 +2443,7 @@ void Configuration::impl::host_info_results (QHostInfo host_info) else { auto const& server_addresses = host_info.addresses (); - qDebug () << "message server addresses:" << server_addresses; + // qDebug () << "message server addresses:" << server_addresses; if (server_addresses.size ()) { check_multicast (server_addresses[0]); diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 2e721d5f7..5ac6a41c1 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -179,7 +179,7 @@ void MessageClient::impl::start () // bind to an ephemeral port on the selected interface and set // up for sending datagrams bind (interface_addr); - qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress (); + // qDebug () << "Bound to UDP port:" << localPort () << "on:" << localAddress (); // set multicast TTL to limit scope when sending to multicast // group addresses diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index 6745fe0a7..8aadd08a6 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -434,7 +434,7 @@ MessageServer::MessageServer (QObject * parent, QString const& version, QString void MessageServer::start (port_type port, QHostAddress const& multicast_group_address , QSet const& network_interface_names) { - qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names; + // qDebug () << "MessageServer::start port:" << port << "multicast addr:" << multicast_group_address.toString () << "network interfaces:" << network_interface_names; if (port != m_->localPort () || multicast_group_address != m_->multicast_group_address_ || network_interface_names != m_->network_interfaces_) From b816875b4601cb0c2751c812ce36e9143b7886e8 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 00:33:53 +0000 Subject: [PATCH 66/73] Ensure multicast UDP is sent to at least the loop-back interface Also send multicast UDP to every selected network interface. --- Configuration.cpp | 44 ++++++++++++++++++++++++++++++++++----- Configuration.ui | 11 ++++++++-- Network/MessageClient.cpp | 15 +++++++++++-- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index a13dc2723..7bd94b5d4 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -443,7 +443,8 @@ private: void load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *); void update_audio_channels (QComboBox const *, int, QComboBox *, bool); - void load_network_interfaces (CheckableItemComboBox *, QStringList const& current); + void load_network_interfaces (CheckableItemComboBox *, QStringList current); + void validate_network_interfaces (CheckableItemComboBox *); QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -656,6 +657,7 @@ private: int dns_lookup_id_; port_type udp_server_port_; QStringList udp_interface_names_; + QString loopback_interface_name_; int udp_TTL_; QString n1mm_server_name_; port_type n1mm_server_port_; @@ -1085,6 +1087,9 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); + connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, [this] (QString const& /*text*/) { + validate_network_interfaces (ui_->udp_interfaces_combo_box); + }); // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { @@ -2995,7 +3000,7 @@ void Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * com } // load the available network interfaces into the selection combo box -void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList const& current) +void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo_box, QStringList current) { combo_box->clear (); for (auto const& net_if : QNetworkInterface::allInterfaces ()) @@ -3003,11 +3008,13 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo auto flags = QNetworkInterface::IsUp | QNetworkInterface::CanMulticast; if ((net_if.flags () & flags) == flags) { - auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + loopback_interface_name_ = net_if.name (); + } auto item = combo_box->addCheckItem (net_if.humanReadableName () , net_if.name () - , is_loopback || current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); - item->setEnabled (!is_loopback); + , current.contains (net_if.name ()) ? Qt::Checked : Qt::Unchecked); auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); auto hw_addr = net_if.hardwareAddress (); @@ -3029,6 +3036,33 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo } } +// get the select network interfaces from the selection combo box +void Configuration::impl::validate_network_interfaces (CheckableItemComboBox * combo_box) +{ + auto model = static_cast (combo_box->model ()); + bool has_checked {false}; + int loopback_row {-1}; + for (int row = 0; row < model->rowCount (); ++row) + { + if (model->item (row)->data ().toString () == loopback_interface_name_) + { + loopback_row = row; + } + else if (Qt::Checked == model->item (row)->checkState ()) + { + has_checked = true; + } + } + if (loopback_row >= 0) + { + if (!has_checked) + { + model->item (loopback_row)->setCheckState (Qt::Checked); + } + model->item (loopback_row)->setEnabled (has_checked); + } +} + // get the select network interfaces from the selection combo box QStringList Configuration::impl::get_selected_network_interfaces (CheckableItemComboBox * combo_box) { diff --git a/Configuration.ui b/Configuration.ui index 1b6ef8926..17fd1a326 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -1885,7 +1885,7 @@ and DX Grid fields when a 73 or free text message is sent. - <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be broadcast.</p></body></html> + <html><head/><body><p>Enter the service port number of the UDP server that WSJT-X should send updates to. If this is zero no updates will be sent.</p></body></html> 65534 @@ -1903,10 +1903,17 @@ and DX Grid fields when a 73 or free text message is sent. - + + + <html><head/><body><p>When sending updates to a multicast group address it is necessary to specify which network interface(s) to send them to. If the loop-back interface is multicast capable then at least that one will be selected.</p><p>For most users the loop-back interface is all that is needed, that will allow multiple other applications on the same machine to interoperate with WSJT-X. If applications running on other hosts are to receive status updates then a suitable network interface should be used.</p><p>On some Linux systems it may be necessary to enable multicast on the loop-back network interface.</p></body></html> + + + + <html><head/><body><p>Sets the number or router hops that multicast datagrams are allowed to make. Almost everyone should set this to 1 to keep outgoing multicast traffic withn the local subnet.</p></body></html> + 255 diff --git a/Network/MessageClient.cpp b/Network/MessageClient.cpp index 5ac6a41c1..3cf00ee3b 100644 --- a/Network/MessageClient.cpp +++ b/Network/MessageClient.cpp @@ -103,6 +103,7 @@ public: void MessageClient::impl::set_server (QString const& server_name, QStringList const& network_interface_names) { + // qDebug () << "MessageClient server:" << server_name << "port:" << server_port_ << "interfaces:" << network_interface_names; server_.setAddress (server_name); network_interfaces_.clear (); for (auto const& net_if_name : network_interface_names) @@ -447,9 +448,19 @@ void MessageClient::impl::send_message (QByteArray const& message, bool queue_if { if (message != last_message_) // avoid duplicates { - for (auto const& net_if : network_interfaces_) + if (is_multicast_address (server_)) { - setMulticastInterface (net_if); + // send datagram on each selected network interface + std::for_each (network_interfaces_.begin (), network_interfaces_.end () + , [&] (QNetworkInterface const& net_if) { + setMulticastInterface (net_if); + // qDebug () << "Multicast UDP datagram sent to:" << server_ << "port:" << server_port_ << "on:" << multicastInterface ().humanReadableName (); + writeDatagram (message, server_, server_port_); + }); + } + else + { + // qDebug () << "Unicast UDP datagram sent to:" << server_ << "port:" << server_port_; writeDatagram (message, server_, server_port_); } last_message_ = message; From 988fcfac5aebf2151523583ed108ea0fcb61f640 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 01:27:36 +0000 Subject: [PATCH 67/73] Ensure network interfaces validation is run on start up --- Configuration.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 7bd94b5d4..4674087b0 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -444,7 +444,7 @@ private: void update_audio_channels (QComboBox const *, int, QComboBox *, bool); void load_network_interfaces (CheckableItemComboBox *, QStringList current); - void validate_network_interfaces (CheckableItemComboBox *); + Q_SLOT void validate_network_interfaces (QString const&); QStringList get_selected_network_interfaces (CheckableItemComboBox *); Q_SLOT void host_info_results (QHostInfo); void check_multicast (QHostAddress const&); @@ -1087,9 +1087,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network load_network_interfaces (ui_->udp_interfaces_combo_box, udp_interface_names_); QGuiApplication::restoreOverrideCursor (); }); - connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, [this] (QString const& /*text*/) { - validate_network_interfaces (ui_->udp_interfaces_combo_box); - }); + connect (ui_->udp_interfaces_combo_box, &QComboBox::currentTextChanged, this, &Configuration::impl::validate_network_interfaces); // set up LoTW users CSV file fetching connect (&lotw_users_, &LotWUsers::load_finished, [this] () { @@ -3037,9 +3035,9 @@ void Configuration::impl::load_network_interfaces (CheckableItemComboBox * combo } // get the select network interfaces from the selection combo box -void Configuration::impl::validate_network_interfaces (CheckableItemComboBox * combo_box) +void Configuration::impl::validate_network_interfaces (QString const& /*text*/) { - auto model = static_cast (combo_box->model ()); + auto model = static_cast (ui_->udp_interfaces_combo_box->model ()); bool has_checked {false}; int loopback_row {-1}; for (int row = 0; row < model->rowCount (); ++row) From 742c180967cefc15413ba03ddaf9778e931dbe89 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Fri, 6 Nov 2020 01:28:19 +0000 Subject: [PATCH 68/73] Allow message_aggregator example to not join on he loopback interface --- UDPExamples/MessageAggregatorMainWindow.cpp | 41 ++++++++++++++++++--- UDPExamples/MessageAggregatorMainWindow.hpp | 2 + 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index a0fe90c47..63b1e45b5 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -107,13 +107,16 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () auto flags = QNetworkInterface::IsRunning | QNetworkInterface::CanMulticast; if ((net_if.flags () & flags) == flags) { - auto is_loopback = net_if.flags () & QNetworkInterface::IsLoopBack; + if (net_if.flags () & QNetworkInterface::IsLoopBack) + { + loopback_interface_name_ = net_if.name (); + } auto item = network_interfaces_combo_box_->addCheckItem (net_if.humanReadableName () , net_if.name () - , is_loopback ? Qt::Checked : Qt::Unchecked); - item->setEnabled (!is_loopback); - auto tip = QString {"name(index): %1(%2) - %3"}.arg (net_if.name ()).arg (net_if.index ()) - .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); + , Qt::Unchecked); + auto tip = QString {"name(index): %1(%2) - %3"} + .arg (net_if.name ()).arg (net_if.index ()) + .arg (net_if.flags () & QNetworkInterface::IsUp ? "Up" : "Down"); auto hw_addr = net_if.hardwareAddress (); if (hw_addr.size ()) { @@ -131,6 +134,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () item->setToolTip (tip); } } + connect (network_interfaces_combo_box_, &QComboBox::currentTextChanged, this, &MessageAggregatorMainWindow::validate_network_interfaces); + validate_network_interfaces (QString {}); log_table_view_->setModel (log_); log_table_view_->verticalHeader ()->hide (); @@ -369,4 +374,30 @@ void MessageAggregatorMainWindow::change_highlighting (QString const& call, QCol } } +void MessageAggregatorMainWindow::validate_network_interfaces (QString const& /*text*/) +{ + auto model = static_cast (network_interfaces_combo_box_->model ()); + bool has_checked {false}; + int loopback_row {-1}; + for (int row = 0; row < model->rowCount (); ++row) + { + if (model->item (row)->data ().toString () == loopback_interface_name_) + { + loopback_row = row; + } + else if (Qt::Checked == model->item (row)->checkState ()) + { + has_checked = true; + } + } + if (loopback_row >= 0) + { + if (!has_checked) + { + model->item (loopback_row)->setCheckState (Qt::Checked); + } + model->item (loopback_row)->setEnabled (has_checked); + } +} + #include "moc_MessageAggregatorMainWindow.cpp" diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 1bff0d692..71ab89ffe 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -46,6 +46,7 @@ private: void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, bool last_only = false); + Q_SLOT void validate_network_interfaces (QString const&); // maps client id to widgets using ClientsDictionary = QHash; @@ -59,6 +60,7 @@ private: QSpinBox * port_spin_box_; QLineEdit * multicast_group_line_edit_; CheckableItemComboBox * network_interfaces_combo_box_; + QString loopback_interface_name_; QLabel * network_interfaces_form_label_widget_; QTableView * log_table_view_; QListWidget * calls_of_interest_; From 61736eb54c4ab33900aee004472a46410ce94334 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 11 Nov 2020 10:35:02 +0000 Subject: [PATCH 69/73] Chinese and Hong Kong UI translation updates, tnx to Sze-To, VR2UPU --- translations/wsjtx_zh.ts | 14 +++++--------- translations/wsjtx_zh_HK.ts | 14 +++++--------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/translations/wsjtx_zh.ts b/translations/wsjtx_zh.ts index e24a2eef4..cc7652ad6 100644 --- a/translations/wsjtx_zh.ts +++ b/translations/wsjtx_zh.ts @@ -621,7 +621,7 @@ Format: Not found audio device missing - + 音频设备未找到 @@ -2213,12 +2213,12 @@ Error(%2): %3 F High - + F 高 F Low - + F 低 @@ -2338,12 +2338,12 @@ Error(%2): %3 SWL Mode - + SWL模式 Hide lower panel controls to maximize deocde windows - + 隐藏下面板控件最大化解码窗口 @@ -4632,10 +4632,6 @@ Error(%2): %3 An error occurred during read from the audio input device. 从音频输入设备读取时错误. - - Audio data not being fed to the audio input device fast enough. - 音频数据没有足够提供馈送到音频输入设备. - Non-recoverable error, audio input device not usable at this time. diff --git a/translations/wsjtx_zh_HK.ts b/translations/wsjtx_zh_HK.ts index abba2aa13..7bfff1f4e 100644 --- a/translations/wsjtx_zh_HK.ts +++ b/translations/wsjtx_zh_HK.ts @@ -621,7 +621,7 @@ Format: Not found audio device missing - + 音訊設備未找到 @@ -2213,12 +2213,12 @@ Error(%2): %3 F High - + F 高 F Low - + F 低 @@ -2338,12 +2338,12 @@ Error(%2): %3 SWL Mode - + SWL 模式 Hide lower panel controls to maximize deocde windows - + 隱藏下面板控制項以最大化解碼視窗 @@ -4633,10 +4633,6 @@ Error(%2): %3 An error occurred during read from the audio input device. 從音頻輸入設備讀取時錯誤. - - Audio data not being fed to the audio input device fast enough. - 音頻數據沒有足夠提供饋送到音頻輸入設備. - Non-recoverable error, audio input device not usable at this time. From bc2999499a83d699cadbc74ce53b7470e555a4e2 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 11 Nov 2020 11:45:22 +0000 Subject: [PATCH 70/73] =?UTF-8?q?Updates=20Spanish=20UI=20translation,=20t?= =?UTF-8?q?nx=20to=20C=C3=A9dric,=20EA4AC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- translations/wsjtx_es.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/translations/wsjtx_es.ts b/translations/wsjtx_es.ts index b6676a3a1..38da0087a 100644 --- a/translations/wsjtx_es.ts +++ b/translations/wsjtx_es.ts @@ -1776,7 +1776,7 @@ Error: %2 - %3 opening connection to rig conexión de apertura al equipo - abriendo conexión al equipo + se abre la conexión al equipo @@ -2452,12 +2452,12 @@ Error(%2): %3 F High - + F Alto F Low - + F Bajo @@ -2577,12 +2577,12 @@ Error(%2): %3 SWL Mode - + Modo Escucha Hide lower panel controls to maximize deocde windows - + Ocultar panel de controles inferior para maximizar la ventana de decodificados From 92cdcb1ffed209b3592414d470213cb4e66d7189 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 11 Nov 2020 16:22:57 +0000 Subject: [PATCH 71/73] Helper functions for callsign analysis --- Radio.cpp | 12 ++++++++++++ Radio.hpp | 1 + 2 files changed, 13 insertions(+) diff --git a/Radio.cpp b/Radio.cpp index e5b34c35d..56b943739 100644 --- a/Radio.cpp +++ b/Radio.cpp @@ -14,10 +14,16 @@ namespace Radio double constexpr MHz_factor {1.e6}; int constexpr frequency_precsion {6}; + // valid callsign alphabet + QRegularExpression callsign_alphabet_re {R"(^[A-Z0-9/]{3,11}$)"}; + // very loose validation - callsign must contain a letter next to // a number QRegularExpression valid_callsign_regexp {R"(\d[[:alpha:]]|[[:alpha:]]\d)"}; + // standard callsign + QRegularExpression strict_standard_callsign_re {R"(^([A-Z][0-9]?|[0-9][A-Z])[0-9][A-Z]{0,3}$)"}; + // suffixes that are often used and should not be interpreted as a // DXCC Entity prefix used as a suffix QRegularExpression non_prefix_suffix {R"(\A([0-9AMPQR]|QRP|F[DF]|[AM]M|L[HT]|LGT)\z)"}; @@ -112,6 +118,12 @@ namespace Radio return callsign.contains ('/'); } + bool is_77bit_nonstandard_callsign (QString const& callsign) + { + return callsign.contains (callsign_alphabet_re) + && !callsign.contains (strict_standard_callsign_re); + } + // split on first '/' and return the larger portion or the whole if // there is no '/' QString base_callsign (QString callsign) diff --git a/Radio.hpp b/Radio.hpp index e63abf4b8..4cc549b8b 100644 --- a/Radio.hpp +++ b/Radio.hpp @@ -53,6 +53,7 @@ namespace Radio // bool UDP_EXPORT is_callsign (QString const&); bool UDP_EXPORT is_compound_callsign (QString const&); + bool is_77bit_nonstandard_callsign (QString const&); QString UDP_EXPORT base_callsign (QString); QString UDP_EXPORT effective_prefix (QString); } From c7f2fdc404d0a6e759ea97d24e9778201a672732 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 12 Nov 2020 13:30:48 +0000 Subject: [PATCH 72/73] Ensure Tx1 message is used by non-standard callsign holders The only exception is type 2 prefix/suffix calls in non-77-bit modes. --- widgets/mainwindow.cpp | 25 ++++++++++++++----------- widgets/mainwindow.h | 3 ++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index c8af595e4..1b56bb435 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -1817,6 +1817,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog checkMSK144ContestType(); if (m_config.my_callsign () != callsign) { m_baseCall = Radio::base_callsign (m_config.my_callsign ()); + ui->tx1->setEnabled (elide_tx1_not_allowed () || ui->tx1->isEnabled ()); morse_(const_cast (m_config.my_callsign ().toLatin1().constData()), const_cast (icw), &m_ncw, m_config.my_callsign ().length()); } @@ -4504,13 +4505,19 @@ void MainWindow::on_txrb1_toggled (bool status) } } +bool MainWindow::elide_tx1_not_allowed () const +{ + auto const& my_callsign = m_config.my_callsign (); + return + (m_mode=="FT8" && SpecOp::HOUND == m_config.special_op_id()) + || ((m_mode.startsWith ("FT") || "MSK144" == m_mode || "Q65" == m_mode || "FST4" == m_mode) + && Radio::is_77bit_nonstandard_callsign (my_callsign)) + || (my_callsign != m_baseCall && !shortList (my_callsign)); +} + void MainWindow::on_txrb1_doubleClicked () { - if(m_mode=="FT8" and SpecOp::HOUND == m_config.special_op_id()) return; - // skip Tx1, only allowed if not a type 2 compound callsign - auto const& my_callsign = m_config.my_callsign (); - auto is_compound = my_callsign != m_baseCall; - ui->tx1->setEnabled ((is_compound && shortList (my_callsign)) || !ui->tx1->isEnabled ()); + ui->tx1->setEnabled (elide_tx1_not_allowed () || !ui->tx1->isEnabled ()); if (!ui->tx1->isEnabled ()) { // leave time for clicks to complete before setting txrb2 QTimer::singleShot (500, ui->txrb2, SLOT (click ())); @@ -4587,11 +4594,7 @@ void MainWindow::on_txb1_clicked() void MainWindow::on_txb1_doubleClicked() { - if (m_mode=="FT8" and SpecOp::HOUND == m_config.special_op_id()) return; - // skip Tx1, only allowed if not a type 1 compound callsign - auto const& my_callsign = m_config.my_callsign (); - auto is_compound = my_callsign != m_baseCall; - ui->tx1->setEnabled ((is_compound && shortList (my_callsign)) || !ui->tx1->isEnabled ()); + ui->tx1->setEnabled (elide_tx1_not_allowed () || !ui->tx1->isEnabled ()); } void MainWindow::on_txb2_clicked() @@ -7436,7 +7439,7 @@ Type 1 Suffixes: /0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /A /P)", {"Courier", 10}}); m_prefixes->raise (); } -bool MainWindow::shortList(QString callsign) +bool MainWindow::shortList(QString callsign) const { int n=callsign.length(); int i1=callsign.indexOf("/"); diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index 272664e78..13b5f3870 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -356,6 +356,7 @@ private: void foxTest(); void setColorHighlighting(); void chkFT4(); + bool elide_tx1_not_allowed () const; QProcessEnvironment const& m_env; NetworkAccessManager m_network_manager; @@ -709,7 +710,7 @@ private: void stub(); void statusChanged(); void fixStop(); - bool shortList(QString callsign); + bool shortList(QString callsign) const; void transmit (double snr = 99.); void rigFailure (QString const& reason); void pskSetLocal (); From dc169c3a84de7ba25892330e5e0b2ea8803b5b03 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Thu, 12 Nov 2020 13:32:56 +0000 Subject: [PATCH 73/73] Resolve some issues with sequencing of R+rprt and sign-off messages --- widgets/mainwindow.cpp | 81 ++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 1b56bb435..58dcbf60d 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -4932,34 +4932,38 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie m_QSOProgress=ROGER_REPORT; } } else { // no grid on end of msg - QString r=message_words.at (3); - if(m_QSOProgress >= ROGER_REPORT && (r=="RRR" || r.toInt()==73 || "RR73" == r)) { - if(m_mode=="FT4" and r=="RR73") m_dateTimeRcvdRR73=QDateTime::currentDateTimeUtc(); - m_bTUmsg=false; - m_nextCall=""; //### Temporary: disable use of "TU;" message - if(SpecOp::RTTY == m_config.special_op_id() and m_nextCall!="") { -// We're in RTTY contest and have "nextCall" queued up: send a "TU; ..." message + auto const& word_3 = message_words.at (3); + bool word_3_is_int; + auto word_3_as_number = word_3.toInt (&word_3_is_int); + if(m_QSOProgress >= ROGER_REPORT && ("RRR" == word_3 + || (word_3_is_int && word_3_as_number == 73) + || "RR73" == word_3)) { + if(m_mode=="FT4" and "RR73" == word_3) m_dateTimeRcvdRR73=QDateTime::currentDateTimeUtc(); + m_bTUmsg=false; + m_nextCall=""; //### Temporary: disable use of "TU;" message + if(SpecOp::RTTY == m_config.special_op_id() and m_nextCall!="") { + // We're in RTTY contest and have "nextCall" queued up: send a "TU; ..." message + logQSOTimer.start(0); + ui->tx3->setText(ui->tx3->text().remove("TU; ")); + useNextCall(); + QString t="TU; " + ui->tx3->text(); + ui->tx3->setText(t); + m_bTUmsg=true; + } else { + if(SpecOp::RTTY == m_config.special_op_id()) { logQSOTimer.start(0); - ui->tx3->setText(ui->tx3->text().remove("TU; ")); - useNextCall(); - QString t="TU; " + ui->tx3->text(); - ui->tx3->setText(t); - m_bTUmsg=true; + m_ntx=6; + ui->txrb6->setChecked(true); } else { - if(SpecOp::RTTY == m_config.special_op_id()) { - logQSOTimer.start(0); - m_ntx=6; - ui->txrb6->setChecked(true); - } else { - m_ntx=5; - ui->txrb5->setChecked(true); - } + m_ntx=5; + ui->txrb5->setChecked(true); } + } m_QSOProgress = SIGNOFF; } else if((m_QSOProgress >= REPORT || (m_QSOProgress >= REPLYING && (m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4"))) - && r.mid(0,1)=="R") { + && word_3.startsWith ('R')) { m_ntx=4; m_QSOProgress = ROGERS; if(SpecOp::RTTY == m_config.special_op_id()) { @@ -4968,23 +4972,30 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie if(nRpt>=529 and nRpt<=599) m_xRcvd=t[n-2] + " " + t[n-1]; } ui->txrb4->setChecked(true); - } else if(m_QSOProgress>=CALLING and - ((r.toInt()>=-50 && r.toInt()<=49) or (r.toInt()>=529 && r.toInt()<=599))) { - if(SpecOp::EU_VHF==m_config.special_op_id() or - SpecOp::FIELD_DAY==m_config.special_op_id() or - SpecOp::RTTY==m_config.special_op_id()) { - setTxMsg(2); - m_QSOProgress=REPORT; - } else { - if(r.left(2)=="R-" or r.left(2)=="R+") { - setTxMsg(4); - m_QSOProgress=ROGERS; + } else if (m_QSOProgress >= CALLING) + { + if (word_3_is_int + && ((word_3_as_number >= -50 && word_3_as_number <= 49) + || (word_3_as_number >= 529 && word_3_as_number <= 599))) { + if(SpecOp::EU_VHF==m_config.special_op_id() or + SpecOp::FIELD_DAY==m_config.special_op_id() or + SpecOp::RTTY==m_config.special_op_id()) { + setTxMsg(2); + m_QSOProgress=REPORT; + } + else { + setTxMsg (3); + m_QSOProgress = ROGER_REPORT; + } } else { - setTxMsg(3); - m_QSOProgress=ROGER_REPORT; + if (word_3.startsWith ("R-") || word_3.startsWith ("R+")) { + setTxMsg(4); + m_QSOProgress=ROGERS; } } - } else { // nothing for us + } + else + { // nothing for us return; } }