From a84b7cdfd375b31691c40f763319a0b5e280a6b5 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Sun, 26 Apr 2015 16:41:12 +0000 Subject: [PATCH] ------------------------------------------------------------------------ r5297 | bsomervi | 2015-04-26 17:26:54 +0100 (Sun, 26 Apr 2015) | 49 lines Various defect repairs and ambigous behaviour clarifications A regression introduced in v1.5.0-rc1 where PTT on an alternate serial port when using no CAT control is resolved. A regression introduced in v1.5.0-rc1 where the network server field was not being restored in the settings dialog has been resolved. In settings the "Test PTT" button is now styled by checked state. The "Test PTT" button is enabled without needing click "Test CAT" first when no CAT rig control is selected. Various parts of the settings dialog are now disabled when no CAT rig control is selected. These are the "Mode" group, the "Split Operation" group and the "Monitor returns to last used frequency" check box. None of these have any visible impact nor make sense without CAT rig control. Initialization and teardown of rig control internals has been revised to avoid several problems related to timing and when switching between different CAT settings. This includes improvements in having the operating frequency restored between sessions when not using CAT rig control. The initialization of OmniRig connections has been improved, unfortunately it is still possible to get an exception when clicking the "Test CAT" button where just clicking "OK" and leaving the settings dialog will probably work. Some unnecessary CAT commands output during direct rig control have been elided to reduce the level of traffic a little. The handling of some automatically generated free text messages used when the station is a type 2 compound callsign or is working a type 2 compound callsign has been improved. This is related to how a double click on a message of the form "DE TI4/N0URE 73" is double clicked. The new behaviour depends on whether the current "DX Call" matches the call in the message. This resolves the ambiguity as to whether this message is a sign off at the end of a QSO with current operator (a 73 message is generated) or a tail end opportunity where the message should be treated the same as a CQ or QRZ message (WSJT-X QSYs to the frequency, generates messages and selects message one ready to call). This still leaves some potential ambiguous behaviors in this complex area but selecting "Clear DX call and grid after logging" should resolve most of them. Rig control trace messages have been cleaned up and are now more helpful, less verbose and, tidier in the source code. ------------------------------------------------------------------------ Merged from the wsjtx-1.5 branch. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5298 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- Configuration.cpp | 494 +++++++++------------- Configuration.hpp | 1 + Configuration.ui | 24 +- DXLabSuiteCommanderTransceiver.cpp | 96 +---- HRDTransceiver.cpp | 169 ++------ HamlibTransceiver.cpp | 638 ++++++++++++----------------- HamlibTransceiver.hpp | 19 +- OmniRigTransceiver.cpp | 197 +++------ PollingTransceiver.cpp | 152 +++---- PollingTransceiver.hpp | 28 +- Transceiver.hpp | 6 +- TransceiverBase.cpp | 141 +++---- TransceiverBase.hpp | 28 +- TransceiverFactory.cpp | 110 +---- TransceiverFactory.hpp | 72 ++-- mainwindow.cpp | 61 ++- qt_helpers.hpp | 2 +- 17 files changed, 869 insertions(+), 1369 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index f1c4359a3..a9d362547 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -50,7 +50,7 @@ // queries. This should be the only place where a hard coded value for // a settings item is defined. Any remaining one-time UI // initialization is also done. At the end of the constructor a method -// initialise_models() is called to load the UI with the current +// initialize_models() is called to load the UI with the current // settings values. // // 2) When the settings UI is displayed by a client calling the exec() @@ -65,7 +65,7 @@ // // 4) If the user discards the settings changes by dismissing the UI // with the "Cancel" button; the reject() operation is called. The -// reject() operation calls initialise_models() which will revert all +// reject() operation calls initialize_models() which will revert all // the UI visible state to the values as at the initial exec() // operation. No changes are moved into the data fields in // Configuration::impl that reflect the settings state published by @@ -107,7 +107,7 @@ // default value. If the setting value is dynamic, add a signal emit // call to broadcast the setting value change. // -// 6) Add code to initialise_models() to load the widget control's +// 6) Add code to initialize_models() to load the widget control's // data model with the current value. // // 7) If there is no convenient data model field, add a data member to @@ -135,6 +135,7 @@ #include #include +#include #include #include #include @@ -335,40 +336,6 @@ public: }; -// Fields that are transceiver related. -// -// These are aggregated in a structure to enable a non-equivalence to -// be provided. -// -// don't forget to update the != operator if any fields are added -// otherwise rig parameter changes will not trigger reconfiguration -struct RigParams -{ - QString CAT_serial_port_; - QString CAT_network_port_; - qint32 CAT_baudrate_; - TransceiverFactory::DataBits CAT_data_bits_; - TransceiverFactory::StopBits CAT_stop_bits_; - TransceiverFactory::Handshake CAT_handshake_; - bool CAT_force_control_lines_; - bool CAT_DTR_high_; - bool CAT_RTS_high_; - qint32 CAT_poll_interval_; - TransceiverFactory::PTTMethod PTT_method_; - QString PTT_port_; - TransceiverFactory::TXAudioSource TX_audio_source_; - TransceiverFactory::SplitMode split_mode_; - QString rig_name_; -}; -bool operator != (RigParams const&, RigParams const&); - -inline -bool operator == (RigParams const& lhs, RigParams const& rhs) -{ - return !(lhs != rhs); -} - - // Internal implementation of the Configuration class. class Configuration::impl final : public QDialog @@ -407,10 +374,11 @@ private: void set_application_font (QFont const&); - void initialise_models (); + void initialize_models (); bool open_rig (); //bool set_mode (); void close_rig (); + TransceiverFactory::ParameterPack gather_rig_data (); void enumerate_rigs (); void set_rig_invariants (); bool validate (); @@ -428,7 +396,7 @@ private: Q_SLOT void on_CAT_poll_interval_spin_box_valueChanged (int); Q_SLOT void on_split_mode_button_group_buttonClicked (int); Q_SLOT void on_test_CAT_push_button_clicked (); - Q_SLOT void on_test_PTT_push_button_clicked (); + Q_SLOT void on_test_PTT_push_button_clicked (bool checked); Q_SLOT void on_CAT_control_lines_group_box_toggled (bool); Q_SLOT void on_CAT_DTR_check_box_toggled (bool); Q_SLOT void on_CAT_RTS_check_box_toggled (bool); @@ -457,6 +425,7 @@ private: Q_SLOT void on_pbNewCall_clicked(); // typenames used as arguments must match registered type names :( + Q_SIGNAL void start_transceiver () const; Q_SIGNAL void stop_transceiver () const; Q_SIGNAL void frequency (Frequency rx, Transceiver::MODE) const; Q_SIGNAL void tx_frequency (Frequency tx, bool rationalize_mode) const; @@ -468,6 +437,7 @@ private: QThread transceiver_thread_; TransceiverFactory transceiver_factory_; + QList rig_connections_; Ui::configuration_dialog * ui_; @@ -511,14 +481,13 @@ private: QAction * station_insert_action_; StationDialog * station_dialog_; - RigParams rig_params_; - RigParams saved_rig_params_; + TransceiverFactory::ParameterPack rig_params_; + TransceiverFactory::ParameterPack saved_rig_params_; bool rig_is_dummy_; bool rig_active_; bool have_rig_; bool rig_changed_; TransceiverState cached_rig_state_; - bool ptt_state_; // the following members are required to get the rig into split the // first time monitor or tune or Tx occur @@ -626,7 +595,7 @@ bool Configuration::id_after_73 () const {return m_->id_after_73_;} bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;} bool Configuration::spot_to_psk_reporter () const {return m_->spot_to_psk_reporter_;} bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;} -bool Configuration::monitor_last_used () const {return m_->monitor_last_used_;} +bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;} bool Configuration::log_as_RTTY () const {return m_->log_as_RTTY_;} bool Configuration::report_in_comments () const {return m_->report_in_comments_;} bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;} @@ -642,7 +611,7 @@ bool Configuration::enable_VHF_features () const {return m_->enable_VHF_features bool Configuration::decode_at_52s () const {return m_->decode_at_52s_;} bool Configuration::split_mode () const { - return !m_->rig_is_dummy_ && m_->rig_params_.split_mode_ != TransceiverFactory::split_mode_none; + return !m_->rig_is_dummy_ && m_->rig_params_.split_mode != TransceiverFactory::split_mode_none; } QString Configuration::udp_server_name () const {return m_->udp_server_name_;} auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;} @@ -654,7 +623,7 @@ StationList * Configuration::stations () {return &m_->stations_;} FrequencyList * Configuration::frequencies () {return &m_->frequencies_;} QStringListModel * Configuration::macros () {return &m_->macros_;} QDir Configuration::save_directory () const {return m_->save_directory_;} -QString Configuration::rig_name () const {return m_->rig_params_.rig_name_;} +QString Configuration::rig_name () const {return m_->rig_params_.rig_name;} bool Configuration::transceiver_online (bool open_if_closed) { @@ -742,7 +711,7 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget * , rig_active_ {false} , have_rig_ {false} , rig_changed_ {false} - , ptt_state_ {false} + // , ptt_state_ {false} , setup_split_ {false} , required_tx_frequency_ {0} , enforce_mode_and_split_ {false} @@ -966,7 +935,7 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget * restart_sound_output_device_ = false; enumerate_rigs (); - initialise_models (); + initialize_models (); transceiver_thread_.start (); @@ -987,7 +956,7 @@ Configuration::impl::~impl () temp_dir_.removeRecursively (); // clean up temp files } -void Configuration::impl::initialise_models () +void Configuration::impl::initialize_models () { auto pal = ui_->callsign_line_edit->palette (); if (my_callsign_.isEmpty ()) @@ -1008,7 +977,7 @@ void Configuration::impl::initialise_models () ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name())); ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name())); ui_->CW_id_interval_spin_box->setValue (id_interval_); - ui_->PTT_method_button_group->button (rig_params_.PTT_method_)->setChecked (true); + ui_->PTT_method_button_group->button (rig_params_.ptt_type)->setChecked (true); ui_->save_path_display_label->setText (save_directory_.absolutePath ()); ui_->CW_id_after_73_check_box->setChecked (id_after_73_); ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_); @@ -1032,25 +1001,25 @@ void Configuration::impl::initialise_models () ui_->jt9w_min_dt_double_spin_box->setValue (jt9w_min_dt_); ui_->jt9w_max_dt_double_spin_box->setValue (jt9w_max_dt_); ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_); - ui_->rig_combo_box->setCurrentText (rig_params_.rig_name_); + ui_->rig_combo_box->setCurrentText (rig_params_.rig_name); ui_->TX_mode_button_group->button (data_mode_)->setChecked (true); - ui_->split_mode_button_group->button (rig_params_.split_mode_)->setChecked (true); - ui_->CAT_serial_baud_combo_box->setCurrentText (QString::number (rig_params_.CAT_baudrate_)); - ui_->CAT_data_bits_button_group->button (rig_params_.CAT_data_bits_)->setChecked (true); - ui_->CAT_stop_bits_button_group->button (rig_params_.CAT_stop_bits_)->setChecked (true); - ui_->CAT_handshake_button_group->button (rig_params_.CAT_handshake_)->setChecked (true); - ui_->CAT_control_lines_group_box->setChecked (rig_params_.CAT_force_control_lines_); - ui_->CAT_DTR_check_box->setChecked (rig_params_.CAT_DTR_high_); - ui_->CAT_RTS_check_box->setChecked (rig_params_.CAT_RTS_high_); - ui_->TX_audio_source_button_group->button (rig_params_.TX_audio_source_)->setChecked (true); - ui_->CAT_poll_interval_spin_box->setValue (rig_params_.CAT_poll_interval_); + ui_->split_mode_button_group->button (rig_params_.split_mode)->setChecked (true); + ui_->CAT_serial_baud_combo_box->setCurrentText (QString::number (rig_params_.baud)); + ui_->CAT_data_bits_button_group->button (rig_params_.data_bits)->setChecked (true); + ui_->CAT_stop_bits_button_group->button (rig_params_.stop_bits)->setChecked (true); + ui_->CAT_handshake_button_group->button (rig_params_.handshake)->setChecked (true); + ui_->CAT_control_lines_group_box->setChecked (rig_params_.force_line_control); + ui_->CAT_DTR_check_box->setChecked (rig_params_.dtr_high); + ui_->CAT_RTS_check_box->setChecked (rig_params_.rts_high); + ui_->TX_audio_source_button_group->button (rig_params_.audio_source)->setChecked (true); + ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval); ui_->udp_server_line_edit->setText (udp_server_name_); ui_->udp_server_port_spin_box->setValue (udp_server_port_); ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_); ui_->udpWindowToFront->setChecked(udpWindowToFront_); ui_->udpWindowRestore->setChecked(udpWindowRestore_); - if (rig_params_.PTT_port_.isEmpty ()) + if (rig_params_.ptt_port.isEmpty ()) { if (ui_->PTT_port_combo_box->count ()) { @@ -1059,7 +1028,7 @@ void Configuration::impl::initialise_models () } else { - ui_->PTT_port_combo_box->setCurrentText (rig_params_.PTT_port_); + ui_->PTT_port_combo_box->setCurrentText (rig_params_.ptt_port); } next_macros_.setStringList (macros_.stringList ()); @@ -1199,20 +1168,20 @@ void Configuration::impl::read_settings () log_as_RTTY_ = settings_->value ("toRTTY", false).toBool (); report_in_comments_ = settings_->value("dBtoComments", false).toBool (); - rig_params_.rig_name_ = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString (); - rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name_; - rig_params_.CAT_network_port_ = settings_->value ("CATNetworkPort").toString (); - rig_params_.CAT_serial_port_ = settings_->value ("CATSerialPort").toString (); - rig_params_.CAT_baudrate_ = settings_->value ("CATSerialRate", 4800).toInt (); - rig_params_.CAT_data_bits_ = settings_->value ("CATDataBits", QVariant::fromValue (TransceiverFactory::eight_data_bits)).value (); - rig_params_.CAT_stop_bits_ = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value (); - rig_params_.CAT_handshake_ = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value (); - rig_params_.CAT_force_control_lines_ = settings_->value ("CATForceControlLines", false).toBool (); - rig_params_.CAT_DTR_high_ = settings_->value ("DTR", false).toBool (); - rig_params_.CAT_RTS_high_ = settings_->value ("RTS", false).toBool (); - rig_params_.PTT_method_ = settings_->value ("PTTMethod", QVariant::fromValue (TransceiverFactory::PTT_method_VOX)).value (); - rig_params_.TX_audio_source_ = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value (); - rig_params_.PTT_port_ = settings_->value ("PTTport").toString (); + rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString (); + rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name; + rig_params_.network_port = settings_->value ("CATNetworkPort").toString (); + rig_params_.serial_port = settings_->value ("CATSerialPort").toString (); + rig_params_.baud = settings_->value ("CATSerialRate", 4800).toInt (); + rig_params_.data_bits = settings_->value ("CATDataBits", QVariant::fromValue (TransceiverFactory::eight_data_bits)).value (); + rig_params_.stop_bits = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value (); + rig_params_.handshake = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value (); + rig_params_.force_line_control = settings_->value ("CATForceControlLines", false).toBool (); + rig_params_.dtr_high = settings_->value ("DTR", false).toBool (); + rig_params_.rts_high = settings_->value ("RTS", false).toBool (); + rig_params_.ptt_type = settings_->value ("PTTMethod", QVariant::fromValue (TransceiverFactory::PTT_method_VOX)).value (); + rig_params_.audio_source = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value (); + rig_params_.ptt_port = settings_->value ("PTTport").toString (); data_mode_ = settings_->value ("DataMode", QVariant::fromValue (data_mode_none)).value (); prompt_to_log_ = settings_->value ("PromptToLog", false).toBool (); insert_blank_ = settings_->value ("InsertBlank", false).toBool (); @@ -1225,8 +1194,8 @@ void Configuration::impl::read_settings () TX_messages_ = settings_->value ("Tx2QSO", false).toBool (); enable_VHF_features_ = settings_->value("VHFUHF",false).toBool (); decode_at_52s_ = settings_->value("Decode52",false).toBool (); - rig_params_.CAT_poll_interval_ = settings_->value ("Polling", 0).toInt (); - rig_params_.split_mode_ = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value (); + rig_params_.poll_interval = settings_->value ("Polling", 0).toInt (); + rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value (); udp_server_name_ = settings_->value ("UDPServer", "localhost").toString (); udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt (); accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool (); @@ -1248,8 +1217,8 @@ void Configuration::impl::write_settings () settings_->setValue ("Font", font_.toString ()); settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ()); settings_->setValue ("IDint", id_interval_); - settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.PTT_method_)); - settings_->setValue ("PTTport", rig_params_.PTT_port_); + settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.ptt_type)); + settings_->setValue ("PTTport", rig_params_.ptt_port); settings_->setValue ("SaveDir", save_directory_.absolutePath ()); if (default_audio_input_device_selected_) @@ -1286,13 +1255,13 @@ void Configuration::impl::write_settings () settings_->setValue ("stations", QVariant::fromValue (stations_.stations ())); settings_->setValue ("toRTTY", log_as_RTTY_); settings_->setValue ("dBtoComments", report_in_comments_); - settings_->setValue ("Rig", rig_params_.rig_name_); - settings_->setValue ("CATNetworkPort", rig_params_.CAT_network_port_); - settings_->setValue ("CATSerialPort", rig_params_.CAT_serial_port_); - settings_->setValue ("CATSerialRate", rig_params_.CAT_baudrate_); - settings_->setValue ("CATDataBits", QVariant::fromValue (rig_params_.CAT_data_bits_)); - settings_->setValue ("CATStopBits", QVariant::fromValue (rig_params_.CAT_stop_bits_)); - settings_->setValue ("CATHandshake", QVariant::fromValue (rig_params_.CAT_handshake_)); + settings_->setValue ("Rig", rig_params_.rig_name); + settings_->setValue ("CATNetworkPort", rig_params_.network_port); + settings_->setValue ("CATSerialPort", rig_params_.serial_port); + settings_->setValue ("CATSerialRate", rig_params_.baud); + settings_->setValue ("CATDataBits", QVariant::fromValue (rig_params_.data_bits)); + settings_->setValue ("CATStopBits", QVariant::fromValue (rig_params_.stop_bits)); + settings_->setValue ("CATHandshake", QVariant::fromValue (rig_params_.handshake)); settings_->setValue ("DataMode", QVariant::fromValue (data_mode_)); settings_->setValue ("PromptToLog", prompt_to_log_); settings_->setValue ("InsertBlank", insert_blank_); @@ -1303,12 +1272,12 @@ void Configuration::impl::write_settings () settings_->setValue ("73TxDisable", disable_TX_on_73_); settings_->setValue ("Runaway", watchdog_); settings_->setValue ("Tx2QSO", TX_messages_); - settings_->setValue ("CATForceControlLines", rig_params_.CAT_force_control_lines_); - settings_->setValue ("DTR", rig_params_.CAT_DTR_high_); - settings_->setValue ("RTS", rig_params_.CAT_RTS_high_); - settings_->setValue ("TXAudioSource", QVariant::fromValue (rig_params_.TX_audio_source_)); - settings_->setValue ("Polling", rig_params_.CAT_poll_interval_); - settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode_)); + settings_->setValue ("CATForceControlLines", rig_params_.force_line_control); + settings_->setValue ("DTR", rig_params_.dtr_high); + settings_->setValue ("RTS", rig_params_.rts_high); + settings_->setValue ("TXAudioSource", QVariant::fromValue (rig_params_.audio_source)); + settings_->setValue ("Polling", rig_params_.poll_interval); + settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode)); settings_->setValue ("VHFUHF", enable_VHF_features_); settings_->setValue ("Decode52", decode_at_52s_); settings_->setValue ("UDPServer", udp_server_name_); @@ -1342,11 +1311,26 @@ void Configuration::impl::set_rig_invariants () if (TransceiverFactory::basic_transceiver_name_ == rig) { + // makes no sense with rig as "None" + ui_->monitor_last_used_check_box->setEnabled (false); + ui_->CAT_control_group_box->setEnabled (false); + ui_->test_CAT_push_button->setEnabled (false); + ui_->test_PTT_push_button->setEnabled (TransceiverFactory::PTT_method_DTR == ptt_method + || TransceiverFactory::PTT_method_RTS == ptt_method); + ui_->TX_audio_source_group_box->setEnabled (false); + ui_->mode_group_box->setEnabled (false); + ui_->split_operation_group_box->setEnabled (false); } else { + ui_->monitor_last_used_check_box->setEnabled (true); ui_->CAT_control_group_box->setEnabled (true); + ui_->test_CAT_push_button->setEnabled (true); + ui_->test_PTT_push_button->setEnabled (false); + ui_->TX_audio_source_group_box->setEnabled (transceiver_factory_.has_CAT_PTT_mic_data (rig) && TransceiverFactory::PTT_method_CAT == ptt_method); + ui_->mode_group_box->setEnabled (true); + ui_->split_operation_group_box->setEnabled (true); if (port_type != last_port_type) { last_port_type = port_type; @@ -1354,7 +1338,7 @@ void Configuration::impl::set_rig_invariants () { case TransceiverFactory::Capabilities::serial: fill_port_combo_box (ui_->CAT_port_combo_box); - ui_->CAT_port_combo_box->setCurrentText (rig_params_.CAT_serial_port_); + ui_->CAT_port_combo_box->setCurrentText (rig_params_.serial_port); if (ui_->CAT_port_combo_box->currentText ().isEmpty () && ui_->CAT_port_combo_box->count ()) { ui_->CAT_port_combo_box->setCurrentText (ui_->CAT_port_combo_box->itemText (0)); @@ -1365,7 +1349,8 @@ void Configuration::impl::set_rig_invariants () break; case TransceiverFactory::Capabilities::network: - ui_->CAT_port_combo_box->setCurrentText (rig_params_.CAT_network_port_); + ui_->CAT_port_combo_box->clear (); + ui_->CAT_port_combo_box->setCurrentText (rig_params_.network_port); ui_->CAT_port_label->setText (tr ("Network Server:")); ui_->CAT_port_combo_box->setToolTip (tr ("Optional hostname and port of network service.\n" "Leave blank for a sensible default on this machine.\n" @@ -1373,7 +1358,6 @@ void Configuration::impl::set_rig_invariants () "\thostname:port\n" "\tIPv4-address:port\n" "\t[IPv6-address]:port")); - ui_->CAT_port_combo_box->clear (); ui_->CAT_port_combo_box->setEnabled (true); break; @@ -1389,16 +1373,6 @@ void Configuration::impl::set_rig_invariants () auto const& cat_port = ui_->CAT_port_combo_box->currentText (); - ui_->TX_audio_source_group_box->setEnabled (transceiver_factory_.has_CAT_PTT_mic_data (rig) && TransceiverFactory::PTT_method_CAT == ptt_method); - - // if (ui_->test_PTT_push_button->isEnabled ()) // don't enable if disabled - "Test CAT" must succeed first - // { - // ui_->test_PTT_push_button->setEnabled ((TransceiverFactory::PTT_method_CAT == ptt_method && CAT_PTT_enabled) - // || TransceiverFactory::PTT_method_DTR == ptt_method - // || TransceiverFactory::PTT_method_RTS == ptt_method); - // } - ui_->test_PTT_push_button->setEnabled (false); - // only enable CAT option if transceiver has CAT PTT ui_->PTT_CAT_radio_button->setEnabled (CAT_PTT_enabled); @@ -1443,13 +1417,6 @@ bool Configuration::impl::validate () return false; } - // auto CAT_port = ui_->CAT_port_combo_box->currentText (); - // if (ui_->CAT_port_combo_box->isEnabled () && CAT_port.isEmpty ()) - // { - // message_box (tr ("Invalid CAT port")); - // return false; - // } - auto ptt_method = static_cast (ui_->PTT_method_button_group->checkedId ()); auto ptt_port = ui_->PTT_port_combo_box->currentText (); if ((TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_RTS == ptt_method) @@ -1468,17 +1435,49 @@ int Configuration::impl::exec () // macros can be modified in the main window next_macros_.setStringList (macros_.stringList ()); - ptt_state_ = false; have_rig_ = rig_active_; // record that we started with a rig open - saved_rig_params_ = rig_params_; // used to detect changes that - // require the Transceiver to be - // re-opened + // require the Transceiver to be + // re-opened rig_changed_ = false; + initialize_models (); return QDialog::exec(); } +TransceiverFactory::ParameterPack Configuration::impl::gather_rig_data () +{ + TransceiverFactory::ParameterPack result; + result.rig_name = ui_->rig_combo_box->currentText (); + + switch (transceiver_factory_.CAT_port_type (result.rig_name)) + { + case TransceiverFactory::Capabilities::network: + result.network_port = ui_->CAT_port_combo_box->currentText (); + result.serial_port = rig_params_.serial_port; + break; + + default: + result.serial_port = ui_->CAT_port_combo_box->currentText (); + result.network_port = rig_params_.network_port; + break; + } + + result.baud = ui_->CAT_serial_baud_combo_box->currentText ().toInt (); + result.data_bits = static_cast (ui_->CAT_data_bits_button_group->checkedId ()); + result.stop_bits = static_cast (ui_->CAT_stop_bits_button_group->checkedId ()); + result.handshake = static_cast (ui_->CAT_handshake_button_group->checkedId ()); + result.force_line_control = ui_->CAT_control_lines_group_box->isChecked (); + result.dtr_high = ui_->CAT_DTR_check_box->isChecked (); + result.rts_high = ui_->CAT_RTS_check_box->isChecked (); + result.poll_interval = ui_->CAT_poll_interval_spin_box->value (); + result.ptt_type = static_cast (ui_->PTT_method_button_group->checkedId ()); + result.ptt_port = ui_->PTT_port_combo_box->currentText (); + result.audio_source = static_cast (ui_->TX_audio_source_button_group->checkedId ()); + result.split_mode = static_cast (ui_->split_mode_button_group->checkedId ()); + return result; +} + void Configuration::impl::accept () { // Called when OK button is clicked. @@ -1491,39 +1490,7 @@ void Configuration::impl::accept () // extract all rig related configuration parameters into temporary // structure for checking if the rig needs re-opening without // actually updating our live state - RigParams temp_rig_params; - temp_rig_params.rig_name_ = ui_->rig_combo_box->currentText (); - - switch (transceiver_factory_.CAT_port_type (temp_rig_params.rig_name_)) - { - case TransceiverFactory::Capabilities::serial: - temp_rig_params.CAT_serial_port_ = ui_->CAT_port_combo_box->currentText (); - temp_rig_params.CAT_network_port_ = rig_params_.CAT_network_port_; - break; - - case TransceiverFactory::Capabilities::network: - temp_rig_params.CAT_network_port_ = ui_->CAT_port_combo_box->currentText (); - temp_rig_params.CAT_serial_port_ = rig_params_.CAT_serial_port_; - break; - - default: - temp_rig_params.CAT_serial_port_ = rig_params_.CAT_serial_port_; - temp_rig_params.CAT_network_port_ = rig_params_.CAT_network_port_; - break; - } - - temp_rig_params.CAT_baudrate_ = ui_->CAT_serial_baud_combo_box->currentText ().toInt (); - temp_rig_params.CAT_data_bits_ = static_cast (ui_->CAT_data_bits_button_group->checkedId ()); - temp_rig_params.CAT_stop_bits_ = static_cast (ui_->CAT_stop_bits_button_group->checkedId ()); - temp_rig_params.CAT_handshake_ = static_cast (ui_->CAT_handshake_button_group->checkedId ()); - temp_rig_params.CAT_force_control_lines_ = ui_->CAT_control_lines_group_box->isChecked (); - temp_rig_params.CAT_DTR_high_ = ui_->CAT_DTR_check_box->isChecked (); - temp_rig_params.CAT_RTS_high_ = ui_->CAT_RTS_check_box->isChecked (); - temp_rig_params.CAT_poll_interval_ = ui_->CAT_poll_interval_spin_box->value (); - temp_rig_params.PTT_method_ = static_cast (ui_->PTT_method_button_group->checkedId ()); - temp_rig_params.PTT_port_ = ui_->PTT_port_combo_box->currentText (); - temp_rig_params.TX_audio_source_ = static_cast (ui_->TX_audio_source_button_group->checkedId ()); - temp_rig_params.split_mode_ = static_cast (ui_->split_mode_button_group->checkedId ()); + auto temp_rig_params = gather_rig_data (); // open_rig() uses values from models so we use it to validate the // Transceiver settings before agreeing to accept the configuration @@ -1565,7 +1532,7 @@ void Configuration::impl::accept () rig_params_ = temp_rig_params; // now we can go live with the rig // related configuration parameters - rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name_; + rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name; // Check to see whether SoundInThread must be restarted, // and save user parameters. @@ -1709,7 +1676,7 @@ void Configuration::impl::accept () void Configuration::impl::reject () { - initialise_models (); // reverts to settings as at exec () + initialize_models (); // reverts to settings as at exec () // check if the Transceiver instance changed, in which case we need // to re open any prior Transceiver type @@ -1871,19 +1838,19 @@ void Configuration::impl::on_test_CAT_push_button_clicked () set_rig_invariants (); } -void Configuration::impl::on_test_PTT_push_button_clicked () +void Configuration::impl::on_test_PTT_push_button_clicked (bool checked) { + ui_->test_PTT_push_button->setChecked (!checked); // let status + // update check us if (!validate ()) { return; } - Q_EMIT self_->transceiver_ptt ((ptt_state_ = !ptt_state_)); - - ui_->test_PTT_push_button->setStyleSheet (ptt_state_ ? "QPushButton{background-color: red;" - "border-style: outset; border-width: 1px; border-radius: 5px;" - "border-color: black; min-width: 5em; padding: 3px;}" - : ""); + if (open_rig ()) + { + Q_EMIT self_->transceiver_ptt (checked); + } } void Configuration::impl::on_CAT_control_lines_group_box_toggled (bool /* checked */) @@ -2034,7 +2001,7 @@ void Configuration::impl::on_save_path_select_push_button_clicked (bool /* check bool Configuration::impl::have_rig (bool open_if_closed) { - if (open_if_closed && !rig_active_ && !open_rig ()) + if (open_if_closed && !open_rig ()) { QMessageBox::critical (this, "WSJT-X", tr ("Failed to open connection to rig")); } @@ -2045,84 +2012,76 @@ bool Configuration::impl::open_rig () { auto result = false; - try + auto const rig_data = gather_rig_data (); + if (!rig_active_ || rig_data != saved_rig_params_) { - close_rig (); - - // create a new Transceiver object - TransceiverFactory::LineControl DTR {TransceiverFactory::no_control}; - TransceiverFactory::LineControl RTS {TransceiverFactory::no_control}; - if (ui_->CAT_control_lines_group_box->isChecked ()) + try { - DTR = ui_->CAT_DTR_check_box->isEnabled () && ui_->CAT_DTR_check_box->isChecked () ? TransceiverFactory::force_high : TransceiverFactory::force_low; - RTS = ui_->CAT_RTS_check_box->isEnabled () && ui_->CAT_RTS_check_box->isChecked () ? TransceiverFactory::force_high : TransceiverFactory::force_low; + close_rig (); + + // create a new Transceiver object + auto rig = transceiver_factory_.create (rig_data, &transceiver_thread_); + + // hook up Configuration transceiver control signals to Transceiver slots + // + // these connections cross the thread boundary + rig_connections_ << connect (this, &Configuration::impl::frequency, rig.get (), &Transceiver::frequency); + rig_connections_ << connect (this, &Configuration::impl::tx_frequency, rig.get (), &Transceiver::tx_frequency); + rig_connections_ << connect (this, &Configuration::impl::mode, rig.get (), &Transceiver::mode); + rig_connections_ << connect (this, &Configuration::impl::ptt, rig.get (), &Transceiver::ptt); + rig_connections_ << connect (this, &Configuration::impl::sync, rig.get (), &Transceiver::sync); + + // hook up Transceiver signals to Configuration signals + // + // these connections cross the thread boundary + connect (rig.get (), &Transceiver::update, this, &Configuration::impl::handle_transceiver_update); + connect (rig.get (), &Transceiver::failure, this, &Configuration::impl::handle_transceiver_failure); + + // setup thread safe startup and close down semantics + rig_connections_ << connect (this, &Configuration::impl::start_transceiver, rig.get (), &Transceiver::start); + connect (this, &Configuration::impl::stop_transceiver, rig.get (), &Transceiver::stop); + + auto p = rig.release (); // take ownership + // schedule eventual destruction + // + // must be queued connection to avoid premature self-immolation + // since finished signal is going to be emitted from the object + // that will get destroyed in its own stop slot i.e. a same + // thread signal to slot connection which by default will be + // reduced to a method function call. + connect (p, &Transceiver::finished, p, &Transceiver::deleteLater, Qt::QueuedConnection); + + ui_->test_CAT_push_button->setStyleSheet ({}); + rig_active_ = true; + Q_EMIT start_transceiver (); // start rig on its thread + result = true; + } + catch (std::exception const& e) + { + handle_transceiver_failure (e.what ()); } - auto rig = transceiver_factory_.create (ui_->rig_combo_box->currentText () - , ui_->CAT_port_combo_box->currentText () - , ui_->CAT_serial_baud_combo_box->currentText ().toInt () - , static_cast (ui_->CAT_data_bits_button_group->checkedId ()) - , static_cast (ui_->CAT_stop_bits_button_group->checkedId ()) - , static_cast (ui_->CAT_handshake_button_group->checkedId ()) - , DTR - , RTS - , static_cast (ui_->PTT_method_button_group->checkedId ()) - , static_cast (ui_->TX_audio_source_button_group->checkedId ()) - , static_cast (ui_->split_mode_button_group->checkedId ()) - , ui_->PTT_port_combo_box->currentText () - , ui_->CAT_poll_interval_spin_box->value () * 1000 - , &transceiver_thread_ - ); - // hook up Configuration transceiver control signals to Transceiver slots - // - // these connections cross the thread boundary - connect (this, &Configuration::impl::frequency, rig.get (), &Transceiver::frequency); - connect (this, &Configuration::impl::tx_frequency, rig.get (), &Transceiver::tx_frequency); - connect (this, &Configuration::impl::mode, rig.get (), &Transceiver::mode); - connect (this, &Configuration::impl::ptt, rig.get (), &Transceiver::ptt); - connect (this, &Configuration::impl::sync, rig.get (), &Transceiver::sync); - - // hook up Transceiver signals to Configuration signals - // - // these connections cross the thread boundary - connect (rig.get (), &Transceiver::update, this, &Configuration::impl::handle_transceiver_update); - connect (rig.get (), &Transceiver::failure, this, &Configuration::impl::handle_transceiver_failure); - - // setup thread safe startup and close down semantics - connect (this, &Configuration::impl::stop_transceiver, rig.get (), &Transceiver::stop); - - auto p = rig.release (); // take ownership - // schedule eventual destruction - // - // must be queued connection to avoid premature self-immolation - // since finished signal is going to be emitted from the object - // that will get destroyed in its own stop slot i.e. a same - // thread signal to slot connection which by default will be - // reduced to a method function call. - connect (p, &Transceiver::finished, p, &Transceiver::deleteLater, Qt::QueuedConnection); - - ui_->test_CAT_push_button->setStyleSheet ({}); - rig_active_ = true; - QTimer::singleShot (0, p, SLOT (start ())); // start rig on its thread + saved_rig_params_ = rig_data; + rig_changed_ = true; + } + else + { result = true; } - catch (std::exception const& e) - { - handle_transceiver_failure (e.what ()); - } - - rig_changed_ = true; return result; } void Configuration::impl::transceiver_frequency (Frequency f) { Transceiver::MODE mode {Transceiver::UNK}; - switch (static_cast (ui_->TX_mode_button_group->checkedId ())) + if (ui_->mode_group_box->isEnabled ()) { - case data_mode_USB: mode = Transceiver::USB; break; - case data_mode_data: mode = Transceiver::DIG_U; break; - case data_mode_none: break; + switch (static_cast (ui_->TX_mode_button_group->checkedId ())) + { + case data_mode_USB: mode = Transceiver::USB; break; + case data_mode_data: mode = Transceiver::DIG_U; break; + case data_mode_none: break; + } } if (cached_rig_state_.frequency () != f @@ -2137,38 +2096,6 @@ void Configuration::impl::transceiver_frequency (Frequency f) } } -// bool Configuration::impl::set_mode () -// { -// // Some rigs change frequency when switching between some modes so -// // we need to check if we change mode and not elide the frequency -// // setting in the same as the cached frequency. -// bool mode_changed {false}; - -// auto data_mode = static_cast (ui_->TX_mode_button_group->checkedId ()); - -// // Set mode if we are responsible for it. -// if (data_mode_USB == data_mode && cached_rig_state_.mode () != Transceiver::USB) -// { -// if (Transceiver::USB != cached_rig_state_.mode ()) -// { -// cached_rig_state_.mode (Transceiver::USB); -// Q_EMIT mode (Transceiver::USB, cached_rig_state_.split () && data_mode_none != data_mode_); -// mode_changed = true; -// } -// } -// if (data_mode_data == data_mode && cached_rig_state_.mode () != Transceiver::DIG_U) -// { -// if (Transceiver::DIG_U != cached_rig_state_.mode ()) -// { -// cached_rig_state_.mode (Transceiver::DIG_U); -// Q_EMIT mode (Transceiver::DIG_U, cached_rig_state_.split () && data_mode_none != data_mode_); -// mode_changed = true; -// } -// } - -// return mode_changed; -// } - void Configuration::impl::transceiver_tx_frequency (Frequency f) { if (/* set_mode () || */ cached_rig_state_.tx_frequency () != f || cached_rig_state_.split () != !!f) @@ -2185,7 +2112,9 @@ void Configuration::impl::transceiver_tx_frequency (Frequency f) // Rationalise TX VFO mode if we ask for split and are // responsible for mode. - Q_EMIT tx_frequency (f, cached_rig_state_.split () && data_mode_none != data_mode_); + Q_EMIT tx_frequency (f, cached_rig_state_.split () + && ui_->mode_group_box->isEnabled () + && data_mode_none != data_mode_); } } @@ -2196,14 +2125,14 @@ void Configuration::impl::transceiver_mode (MODE m) cached_rig_state_.mode (m); // Rationalise mode if we are responsible for it and in split mode. - Q_EMIT mode (m, cached_rig_state_.split () && data_mode_none != data_mode_); + Q_EMIT mode (m, cached_rig_state_.split () + && ui_->mode_group_box->isEnabled () + && data_mode_none != data_mode_); } } void Configuration::impl::transceiver_ptt (bool on) { - // set_mode (); - cached_rig_state_.ptt (on); // pass this on regardless of cache @@ -2224,6 +2153,8 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state) if (state.online ()) { + ui_->test_PTT_push_button->setChecked (state.ptt ()); + TransceiverFactory::SplitMode split_mode_selected; if (isVisible ()) { @@ -2236,7 +2167,6 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state) || TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_RTS == ptt_method); - // set_mode (); // Follow the setup choice. split_mode_selected = static_cast (ui_->split_mode_button_group->checkedId ()); @@ -2244,11 +2174,12 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state) else { // Follow the rig unless configuration has been changed. - split_mode_selected = static_cast (rig_params_.split_mode_); + split_mode_selected = static_cast (rig_params_.split_mode); if (enforce_mode_and_split_) { - if ((TransceiverFactory::split_mode_none != split_mode_selected) != state.split ()) + if (TransceiverFactory::basic_transceiver_name_ != ui_->rig_combo_box->currentText () + && ((TransceiverFactory::split_mode_none != split_mode_selected) != state.split ())) { if (!setup_split_) { @@ -2259,7 +2190,7 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state) // (e.g.Icom) this is going to confuse operators, but // what can we do if they change the rig? // auto split_mode = state.split () ? TransceiverFactory::split_mode_rig : TransceiverFactory::split_mode_none; - // rig_params_.split_mode_ = split_mode; + // rig_params_.split_mode = split_mode; // ui_->split_mode_button_group->button (split_mode)->setChecked (true); // split_mode_selected = split_mode; setup_split_ = true; @@ -2269,8 +2200,6 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state) Q_EMIT self_->transceiver_failure (tr ("Rig split mode setting not consistent with WSJT-X settings.")); } } - - // set_mode (); } } @@ -2307,6 +2236,7 @@ void Configuration::impl::handle_transceiver_failure (QString reason) #endif close_rig (); + ui_->test_PTT_push_button->setChecked (false); if (isVisible ()) { @@ -2321,15 +2251,18 @@ void Configuration::impl::handle_transceiver_failure (QString reason) void Configuration::impl::close_rig () { - ui_->test_PTT_push_button->setStyleSheet ({}); ui_->test_PTT_push_button->setEnabled (false); - ptt_state_ = false; // revert to no rig configured if (rig_active_) { ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}"); Q_EMIT stop_transceiver (); + Q_FOREACH (auto const& connection, rig_connections_) + { + disconnect (connection); + } + rig_connections_.clear (); rig_active_ = false; } } @@ -2454,7 +2387,7 @@ void Configuration::impl::enumerate_rigs () } } - ui_->rig_combo_box->setCurrentText (rig_params_.rig_name_); + ui_->rig_combo_box->setCurrentText (rig_params_.rig_name); } void Configuration::impl::fill_port_combo_box (QComboBox * cb) @@ -2474,27 +2407,6 @@ void Configuration::impl::fill_port_combo_box (QComboBox * cb) cb->setEditText (current_text); } -inline -bool operator != (RigParams const& lhs, RigParams const& rhs) -{ - return - lhs.CAT_serial_port_ != rhs.CAT_serial_port_ - || lhs.CAT_network_port_ != rhs.CAT_network_port_ - || lhs.CAT_baudrate_ != rhs.CAT_baudrate_ - || lhs.CAT_data_bits_ != rhs.CAT_data_bits_ - || lhs.CAT_stop_bits_ != rhs.CAT_stop_bits_ - || lhs.CAT_handshake_ != rhs.CAT_handshake_ - || lhs.CAT_force_control_lines_ != rhs.CAT_force_control_lines_ - || lhs.CAT_DTR_high_ != rhs.CAT_DTR_high_ - || lhs.CAT_RTS_high_ != rhs.CAT_RTS_high_ - || lhs.CAT_poll_interval_ != rhs.CAT_poll_interval_ - || lhs.PTT_method_ != rhs.PTT_method_ - || lhs.PTT_port_ != rhs.PTT_port_ - || lhs.TX_audio_source_ != rhs.TX_audio_source_ - || lhs.split_mode_ != rhs.split_mode_ - || lhs.rig_name_ != rhs.rig_name_; -} - #if !defined (QT_NO_DEBUG_STREAM) ENUM_QDEBUG_OPS_IMPL (Configuration, DataMode); diff --git a/Configuration.hpp b/Configuration.hpp index c51a5f04d..4bd6304ce 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -203,6 +203,7 @@ private: pimpl m_; }; + Q_DECLARE_METATYPE (Configuration::DataMode); Q_DECLARE_METATYPE (Configuration::Type2MsgGen); diff --git a/Configuration.ui b/Configuration.ui index 42183c50f..b49044eab 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -1074,10 +1074,24 @@ Click again to deactivate. Normally no power should be output since there is no audio being generated at this time. Check that any Tx indication on your radio and/or your radio interface behave as expected. + + + QPushButton:checked { + background-color: red; + border-style : outset; + border-width: 1px; + border-radius: 5px; + border-color: black; + min-width: 5em; + padding: 3px; +} Test PTT + + true + @@ -2237,12 +2251,12 @@ soundcard changes - - - - - + + + + + diff --git a/DXLabSuiteCommanderTransceiver.cpp b/DXLabSuiteCommanderTransceiver.cpp index 78bfda219..7ef7bb4ce 100644 --- a/DXLabSuiteCommanderTransceiver.cpp +++ b/DXLabSuiteCommanderTransceiver.cpp @@ -54,10 +54,7 @@ DXLabSuiteCommanderTransceiver::~DXLabSuiteCommanderTransceiver () void DXLabSuiteCommanderTransceiver::do_start () { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::start"; -#endif - + TRACE_CAT ("starting"); wrapped_->start (); auto server_details = network_server_lookup (server_, 52002u, QHostAddress::LocalHost, QAbstractSocket::IPv4Protocol); @@ -70,10 +67,7 @@ void DXLabSuiteCommanderTransceiver::do_start () commander_->connectToHost (std::get<0> (server_details), std::get<1> (server_details)); if (!commander_->waitForConnected ()) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::start failed to connect" << commander_->errorString (); -#endif - + TRACE_CAT ("failed to connect" << commander_->errorString ()); throw error {tr ("Failed to connect to DX Lab Suite Commander\n") + commander_->errorString ()}; } @@ -89,18 +83,12 @@ void DXLabSuiteCommanderTransceiver::do_stop () } wrapped_->stop (); - -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::stop"; -#endif + TRACE_CAT ("stopped"); } void DXLabSuiteCommanderTransceiver::do_ptt (bool on) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::do_ptt:" << on << state (); -#endif - + TRACE_CAT (on << state ()); if (use_for_ptt_) { simple_command (on ? "CmdTX" : "CmdRX"); @@ -109,16 +97,12 @@ void DXLabSuiteCommanderTransceiver::do_ptt (bool on) { wrapped_->ptt (on); } - update_PTT (on); } void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::do_frequency:" << f << state (); -#endif - + TRACE_CAT (f << state ()); auto f_string = frequency_to_string (f); if (UNK != m) { @@ -137,10 +121,7 @@ void DXLabSuiteCommanderTransceiver::do_frequency (Frequency f, MODE m) void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::do_tx_frequency:" << tx << state (); -#endif - + TRACE_CAT (tx << state ()); if (tx) { auto f_string = frequency_to_string (tx); @@ -157,15 +138,10 @@ void DXLabSuiteCommanderTransceiver::do_tx_frequency (Frequency tx, bool /* rati void DXLabSuiteCommanderTransceiver::do_mode (MODE m, bool /* rationalise */) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::do_mode:" << m << state (); -#endif - + TRACE_CAT (m << state ()); auto m_string = map_mode (m); auto params = ("<1:%1>" + m_string).arg (m_string.size ()); - simple_command (("CmdSetMode" + params).arg (params.size ())); - update_mode (m); } @@ -192,10 +168,7 @@ void DXLabSuiteCommanderTransceiver::poll () } else { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::poll: get frequency unexpected response"; -#endif - + TRACE_CAT_POLL ("get frequency unexpected response"); throw error {tr ("DX Lab Suite Commander didn't respond correctly polling frequency")}; } @@ -216,10 +189,7 @@ void DXLabSuiteCommanderTransceiver::poll () } else { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::poll: get tx frequency unexpected response"; -#endif - + TRACE_CAT_POLL ("get tx frequency unexpected response"); throw error {tr ("DX Lab Suite Commander didn't respond correctly polling TX frequency")}; } } @@ -238,19 +208,13 @@ void DXLabSuiteCommanderTransceiver::poll () } else { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected split state" << split; -#endif - + TRACE_CAT_POLL ("unexpected split state" << split); throw error {tr ("DX Lab Suite Commander sent an unrecognised split state: ") + split}; } } else { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::poll: get split mode unexpected response"; -#endif - + TRACE_CAT_POLL ("get split mode unexpected response"); throw error {tr ("DX Lab Suite Commander didn't respond correctly polling split status")}; } @@ -301,20 +265,14 @@ void DXLabSuiteCommanderTransceiver::poll () } else { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected mode name" << mode; -#endif - + TRACE_CAT_POLL ("unexpected mode name" << mode); throw error {tr ("DX Lab Suite Commander sent an unrecognised mode: \"") + mode + '"'}; } update_mode (m); } else { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::poll: unexpected response"; -#endif - + TRACE_CAT_POLL ("unexpected response"); throw error {tr ("DX Lab Suite Commander didn't respond correctly polling mode")}; } } @@ -325,17 +283,12 @@ void DXLabSuiteCommanderTransceiver::simple_command (QString const& cmd, bool no if (!no_debug) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver:simple_command(" << cmd << ')'; -#endif + TRACE_CAT (cmd); } if (!write_to_port (cmd)) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::simple_command failed:" << commander_->errorString (); -#endif - + TRACE_CAT ("failed:" << commander_->errorString ()); throw error {tr ("DX Lab Suite Commander send command failed\n") + commander_->errorString ()}; } } @@ -346,10 +299,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd, if (!write_to_port (cmd)) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply failed to send command:" << commander_->errorString (); -#endif - + TRACE_CAT ("failed to send command:" << commander_->errorString ()); throw error { tr ("DX Lab Suite Commander failed to send command \"%1\": %2\n") .arg (cmd) @@ -366,10 +316,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd, replied = commander_->waitForReadyRead (); if (!replied && commander_->error () != commander_->SocketTimeoutError) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply \"" << cmd << "\" failed to read reply:" << commander_->errorString (); -#endif - + TRACE_CAT (cmd << "failed to read reply:" << commander_->errorString ()); throw error { tr ("DX Lab Suite Commander send command \"%1\" read reply failed: %2\n") .arg (cmd) @@ -380,10 +327,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd, if (!replied) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver::command_with_reply \"" << cmd << "\" retries exhausted"; -#endif - + TRACE_CAT (cmd << "retries exhausted"); throw error { tr ("DX Lab Suite Commander retries exhausted sending command \"%1\"") .arg (cmd) @@ -399,9 +343,7 @@ QString DXLabSuiteCommanderTransceiver::command_with_reply (QString const& cmd, if (!no_debug) { -#if WSJT_TRACE_CAT - qDebug () << "DXLabSuiteCommanderTransceiver:command_with_reply(" << cmd << ") ->" << result; -#endif + TRACE_CAT (cmd << "->" << result); } return result; // converting raw UTF-8 bytes to QString diff --git a/HRDTransceiver.cpp b/HRDTransceiver.cpp index 3795a7451..5b3d937bf 100644 --- a/HRDTransceiver.cpp +++ b/HRDTransceiver.cpp @@ -104,26 +104,18 @@ HRDTransceiver::~HRDTransceiver () void HRDTransceiver::do_start () { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::start"; -#endif - + TRACE_CAT ("starting"); wrapped_->start (); auto server_details = network_server_lookup (server_, 7809u); - if (!hrd_) { hrd_ = new QTcpSocket {this}; // QObject takes ownership } - hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details)); if (!hrd_->waitForConnected ()) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::start failed to connect:" << hrd_->errorString (); -#endif - + TRACE_CAT ("failed to connect:" << hrd_->errorString ()); throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()}; } @@ -148,10 +140,7 @@ void HRDTransceiver::do_start () hrd_->connectToHost (std::get<0> (server_details), std::get<1> (server_details)); if (!hrd_->waitForConnected ()) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_start failed to connect:" << hrd_->errorString (); -#endif - + TRACE_CAT ("failed to connect:" << hrd_->errorString ()); throw error {tr ("Failed to connect to Ham Radio Deluxe\n") + hrd_->errorString ()}; } @@ -168,21 +157,14 @@ void HRDTransceiver::do_start () auto id = send_command ("get id", false, false); auto version = send_command ("get version", false, false); -#if WSJT_TRACE_CAT - qDebug () << "Id:" << id; - qDebug () << "Version:" << version; -#endif - + TRACE_CAT ("Id:" << id << "Version:" << version); HRD_info << "Id: " << id << "\n"; HRD_info << "Version: " << version << "\n"; auto radios = send_command ("get radios", false, false).trimmed ().split (',', QString::SkipEmptyParts); if (radios.isEmpty ()) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_start no rig found"; -#endif - + TRACE_CAT ("no rig found"); throw error {tr ("Ham Radio Deluxe: no rig found")}; } @@ -195,10 +177,10 @@ void HRDTransceiver::do_start () } #if WSJT_TRACE_CAT - qDebug () << "radios:"; + TRACE_CAT ("radios:-"); Q_FOREACH (auto const& radio, radios_) { - qDebug () << "\t[" << std::get<0> (radio) << "] " << std::get<1> (radio); + TRACE_CAT ("\t[" << std::get<0> (radio) << "] " << std::get<1> (radio)); } #endif @@ -206,51 +188,36 @@ void HRDTransceiver::do_start () HRD_info << "Current radio: " << current_radio_name << "\n"; if (current_radio_name.isEmpty ()) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_start no rig found"; -#endif - + TRACE_CAT ("no rig found"); throw error {tr ("Ham Radio Deluxe: no rig found")}; } vfo_count_ = send_command ("get vfo-count").toUInt (); HRD_info << "VFO count: " << vfo_count_ << "\n"; -#if WSJT_TRACE_CAT - qDebug () << "vfo count:" << vfo_count_; -#endif + TRACE_CAT ("vfo count:" << vfo_count_); buttons_ = send_command ("get buttons").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~"); -#if WSJT_TRACE_CAT - qDebug () << "HRD Buttons: " << buttons_; -#endif + TRACE_CAT ("HRD Buttons: " << buttons_); HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n"; dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', QString::SkipEmptyParts); -#if WSJT_TRACE_CAT - qDebug () << "Dropdowns:\n"; -#endif + TRACE_CAT ("Dropdowns:"); HRD_info << "Dropdowns:\n"; Q_FOREACH (auto const& dd, dropdown_names_) { auto selections = send_command ("get dropdown-list {" + dd + "}").trimmed ().split (',', QString::SkipEmptyParts); -#if WSJT_TRACE_CAT - qDebug () << "\t" << dd << ": {" << selections.join (", ") << "}\n"; -#endif + TRACE_CAT ("\t" << dd << ": {" << selections.join (", ") << "}"); HRD_info << "\t" << dd << ": {" << selections.join (", ") << "}\n"; dropdowns_[dd] = selections; } slider_names_ = send_command ("get sliders").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~"); -#if WSJT_TRACE_CAT - qDebug () << "Sliders:\n"; -#endif + TRACE_CAT ("Sliders:-"); HRD_info << "Sliders:\n"; Q_FOREACH (auto const& s, slider_names_) { auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', QString::SkipEmptyParts); -#if WSJT_TRACE_CAT - qDebug () << "\t" << s << ": {" << range.join (", ") << "}\n"; -#endif + TRACE_CAT ("\t" << s << ": {" << range.join (", ") << "}"); HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n"; sliders_[s] = range; } @@ -334,10 +301,7 @@ void HRDTransceiver::do_stop () { wrapped_->stop (); } - -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::stop: state:" << state () << "reversed =" << reversed_; -#endif + TRACE_CAT ("stopped" << state () << "reversed" << reversed_); } int HRDTransceiver::find_button (QRegExp const& re) const @@ -384,12 +348,11 @@ void HRDTransceiver::map_modes (int dropdown, ModeMap *map) map->push_back (std::forward_as_tuple (DIG_FM, find_dropdown_selection (dropdown, QRegExp ("^(PKT-FM|PKT|FM)$")))); #if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::map_modes: for dropdown" << dropdown_names_[dropdown]; - + TRACE_CAT ("for dropdown" << dropdown_names_[dropdown]); std::for_each (map->begin (), map->end (), [this, dropdown] (ModeMap::value_type const& item) { auto const& rhs = std::get<1> (item); - qDebug () << '\t' << std::get<0> (item) << "<->" << (rhs.size () ? dropdowns_[dropdown_names_[dropdown]][rhs.front ()] : "None"); + TRACE_CAT ('\t' << std::get<0> (item) << "<->" << (rhs.size () ? dropdowns_[dropdown_names_[dropdown]][rhs.front ()] : "None")); }); #endif } @@ -452,20 +415,14 @@ void HRDTransceiver::set_dropdown (int dd, int value) } else { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::set_dropdown item" << value << "not found in" << dd_name; -#endif - + TRACE_CAT ("item" << value << "not found in" << dd_name); throw error {tr ("Ham Radio Deluxe: item not found in %1 dropdown list").arg (dd_name)}; } } void HRDTransceiver::do_ptt (bool on) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_ptt:" << on; -#endif - + TRACE_CAT (on); if (use_for_ptt_) { if (ptt_button_ >= 0) @@ -491,25 +448,18 @@ void HRDTransceiver::set_button (int button_index, bool checked) } else { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::set_button invalid button"; -#endif - + TRACE_CAT ("invalid button"); throw error {tr ("Ham Radio Deluxe: button not available")}; } } void HRDTransceiver::do_frequency (Frequency f, MODE m) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_frequency:" << f << "reversed:" << reversed_; -#endif - + TRACE_CAT (f << "reversed" << reversed_); if (UNK != m) { do_mode (m, false); } - auto fo_string = QString::number (f); if (vfo_count_ > 1 && reversed_) { @@ -525,9 +475,7 @@ void HRDTransceiver::do_frequency (Frequency f, MODE m) void HRDTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_tx_frequency:" << tx << "rationalize mode:" << rationalise_mode << "reversed:" << reversed_; -#endif + TRACE_CAT (tx << "rationalize mode:" << rationalise_mode << "reversed" << reversed_); // re-check if reversed VFOs bool rx_A {true}; @@ -683,10 +631,7 @@ void HRDTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) void HRDTransceiver::do_mode (MODE mode, bool rationalise) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::do_mode:" << mode; -#endif - + TRACE_CAT (mode); if (reversed_ && mode_B_dropdown_ >= 0) { set_dropdown (mode_B_dropdown_, lookup_mode (mode, mode_B_map_)); @@ -695,7 +640,6 @@ void HRDTransceiver::do_mode (MODE mode, bool rationalise) { set_dropdown (mode_A_dropdown_, lookup_mode (mode, mode_A_map_)); } - if (rationalise && state ().split ()) // rationalise mode if split { if (reversed_) @@ -767,7 +711,6 @@ void HRDTransceiver::do_mode (MODE mode, bool rationalise) } } } - update_mode (mode); } @@ -781,10 +724,7 @@ bool HRDTransceiver::is_button_checked (int button_index, bool no_debug) auto reply = send_command ("get button-select " + buttons_.value (button_index), no_debug); if ("1" != reply && "0" != reply) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::is_button_checked bad response"; -#endif - + TRACE_CAT ("bad response"); throw error {tr ("Ham Radio Deluxe didn't respond as expected")}; } return "1" == reply; @@ -794,7 +734,6 @@ void HRDTransceiver::poll () { #if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS bool quiet {false}; - qDebug () << "+++++++ poll dump +++++++"; qDebug () << "reversed:" << reversed_; is_button_checked (vfo_A_button_); @@ -815,7 +754,6 @@ void HRDTransceiver::poll () get_dropdown (split_mode_dropdown_); } qDebug () << "------- poll dump -------"; - #else bool quiet {true}; #endif @@ -913,10 +851,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr }); if (radio_iter == radios_.end ()) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command rig disappeared or changed"; -#endif - + TRACE_CAT ("rig disappeared or changed"); throw error {tr ("Ham Radio Deluxe: rig has disappeared or changed")}; } @@ -930,10 +865,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr if (QTcpSocket::ConnectedState != hrd_->state ()) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command" << cmd << "failed" << hrd_->errorString (); -#endif - + TRACE_CAT (cmd << "failed" << hrd_->errorString ()); throw error { tr ("Ham Radio Deluxe send command \"%1\" failed %2\n") .arg (cmd) @@ -946,10 +878,7 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr auto message = ((prepend_context ? context + cmd : cmd) + "\r").toLocal8Bit (); if (!write_to_port (message.constData (), message.size ())) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command failed to write command" << cmd << "to HRD"; -#endif - + TRACE_CAT ("failed to write command" << cmd << "to HRD"); throw error { tr ("Ham Radio Deluxe: failed to write command \"%1\"") .arg (cmd) @@ -962,19 +891,14 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr QScopedPointer message {new (string) HRDMessage}; if (!write_to_port (reinterpret_cast (message.data ()), message->size_)) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command failed to write command" << cmd << "to HRD"; -#endif - + TRACE_CAT ("failed to write command" << cmd << "to HRD"); throw error { tr ("Ham Radio Deluxe: failed to write command \"%1\"") .arg (cmd) }; } } - auto buffer = read_reply (cmd); - if (v4 == protocol_) { result = QString {buffer}.trimmed (); @@ -982,13 +906,9 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr else { HRDMessage const * reply {new (buffer) HRDMessage}; - if (reply->magic_1_value_ != reply->magic_1_ && reply->magic_2_value_ != reply->magic_2_) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command" << cmd << "invalid reply"; -#endif - + TRACE_CAT (cmd << "invalid reply"); throw error { tr ("Ham Radio Deluxe sent an invalid reply to our command \"%1\"") .arg (cmd) @@ -998,24 +918,20 @@ QString HRDTransceiver::send_command (QString const& cmd, bool no_debug, bool pr // keep reading until expected size arrives while (buffer.size () - offsetof (HRDMessage, size_) < reply->size_) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command" << cmd << "reading more reply data"; -#endif - + if (!no_debug) + { + TRACE_CAT (cmd << "reading more reply data"); + } buffer += read_reply (cmd); reply = new (buffer) HRDMessage; } result = QString {reply->payload_}; // this is not a memory leak (honest!) } - if (!no_debug) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command(" << cmd << "): ->" << result; -#endif + TRACE_CAT (cmd << " ->" << result); } - return result; } @@ -1046,10 +962,7 @@ QByteArray HRDTransceiver::read_reply (QString const& cmd) replied = hrd_->waitForReadyRead (); if (!replied && hrd_->error () != hrd_->SocketTimeoutError) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command" << cmd << "failed to reply" << hrd_->errorString (); -#endif - + TRACE_CAT (cmd << "failed to reply" << hrd_->errorString ()); throw error { tr ("Ham Radio Deluxe failed to reply to command \"%1\" %2\n") .arg (cmd) @@ -1057,19 +970,14 @@ QByteArray HRDTransceiver::read_reply (QString const& cmd) }; } } - if (!replied) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_command" << cmd << "retries exhausted"; -#endif - + TRACE_CAT (cmd << "retries exhausted"); throw error { tr ("Ham Radio Deluxe retries exhausted sending command \"%1\"") .arg (cmd) }; } - return hrd_->readAll (); } @@ -1077,10 +985,7 @@ void HRDTransceiver::send_simple_command (QString const& command, bool no_debug) { if ("OK" != send_command (command, no_debug)) { -#if WSJT_TRACE_CAT - qDebug () << "HRDTransceiver::send_simple_command" << command << "unexpected response"; -#endif - + TRACE_CAT (command << "unexpected response"); throw error { tr ("Ham Radio Deluxe didn't respond to command \"%1\" as expected") .arg (command) diff --git a/HamlibTransceiver.cpp b/HamlibTransceiver.cpp index bc957c45c..fcad237c2 100644 --- a/HamlibTransceiver.cpp +++ b/HamlibTransceiver.cpp @@ -28,24 +28,25 @@ namespace int debug_callback (enum rig_debug_level_e level, rig_ptr_t /* arg */, char const * format, va_list ap) { QString message; + static char const fmt[] = "Hamlib: %s"; message = message.vsprintf (format, ap).trimmed (); switch (level) { case RIG_DEBUG_BUG: - qFatal ("%s", message.toLocal8Bit ().data ()); + qFatal (fmt, message.toLocal8Bit ().data ()); break; case RIG_DEBUG_ERR: - qCritical ("%s", message.toLocal8Bit ().data ()); + qCritical (fmt, message.toLocal8Bit ().data ()); break; case RIG_DEBUG_WARN: - qWarning ("%s", message.toLocal8Bit ().data ()); + qWarning (fmt, message.toLocal8Bit ().data ()); break; default: - qDebug ("%s", message.toLocal8Bit ().data ()); + qDebug (fmt, message.toLocal8Bit ().data ()); break; } @@ -59,8 +60,7 @@ namespace TransceiverFactory::Transceivers * rigs = reinterpret_cast (callback_data); QString key; - if ("Hamlib" == QString::fromLatin1 (caps->mfg_name).trimmed () - && "Dummy" == QString::fromLatin1 (caps->model_name).trimmed ()) + if (RIG_MODEL_DUMMY == caps->rig_model) { key = TransceiverFactory::basic_transceiver_name_; } @@ -88,7 +88,9 @@ namespace } (*rigs)[key] = TransceiverFactory::Capabilities (caps->rig_model , port_type - , RIG_PTT_RIG == caps->ptt_type || RIG_PTT_RIG_MICDATA == caps->ptt_type + , RIG_MODEL_DUMMY != caps->rig_model + && (RIG_PTT_RIG == caps->ptt_type + || RIG_PTT_RIG_MICDATA == caps->ptt_type) , RIG_PTT_RIG_MICDATA == caps->ptt_type); return 1; // keep them coming @@ -126,6 +128,9 @@ namespace }; } +freq_t HamlibTransceiver::dummy_frequency_; +rmode_t HamlibTransceiver::dummy_mode_ {RIG_MODE_NONE}; + void HamlibTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry) { rig_set_debug_callback (debug_callback, nullptr); @@ -155,22 +160,11 @@ void HamlibTransceiver::RIGDeleter::cleanup (RIG * rig) } } -HamlibTransceiver::HamlibTransceiver (int model_number - , QString const& cat_port - , int cat_baud - , TransceiverFactory::DataBits cat_data_bits - , TransceiverFactory::StopBits cat_stop_bits - , TransceiverFactory::Handshake cat_handshake - , TransceiverFactory::LineControl cat_dtr_control - , TransceiverFactory::LineControl cat_rts_control - , TransceiverFactory::PTTMethod ptt_type - , TransceiverFactory::TXAudioSource back_ptt_port - , QString const& ptt_port - , int poll_interval) - : PollingTransceiver {poll_interval} - , rig_ {rig_init (model_number)} - , back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == back_ptt_port} - , is_dummy_ {RIG_MODEL_DUMMY == model_number} +HamlibTransceiver::HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port) + : PollingTransceiver {0} + , rig_ {rig_init (RIG_MODEL_DUMMY)} + , back_ptt_port_ {false} + , is_dummy_ {true} , reversed_ {false} , split_query_works_ {true} , get_vfo_works_ {true} @@ -180,34 +174,6 @@ HamlibTransceiver::HamlibTransceiver (int model_number throw error {tr ("Hamlib initialisation error")}; } - // rig_->state.obj = this; - - if (!cat_port.isEmpty ()) - { - set_conf ("rig_pathname", cat_port.toLatin1 ().data ()); - } - - set_conf ("serial_speed", QByteArray::number (cat_baud).data ()); - set_conf ("data_bits", TransceiverFactory::seven_data_bits == cat_data_bits ? "7" : "8"); - set_conf ("stop_bits", TransceiverFactory::one_stop_bit == cat_stop_bits ? "1" : "2"); - - switch (cat_handshake) - { - case TransceiverFactory::handshake_none: set_conf ("serial_handshake", "None"); break; - case TransceiverFactory::handshake_XonXoff: set_conf ("serial_handshake", "XONXOFF"); break; - case TransceiverFactory::handshake_hardware: set_conf ("serial_handshake", "Hardware"); break; - } - - if (TransceiverFactory::no_control != cat_dtr_control) - { - set_conf ("dtr_state", TransceiverFactory::force_high == cat_dtr_control ? "ON" : "OFF"); - } - if (TransceiverFactory::handshake_hardware != cat_handshake - && TransceiverFactory::no_control != cat_rts_control) - { - set_conf ("rts_state", TransceiverFactory::force_high == cat_rts_control ? "ON" : "OFF"); - } - switch (ptt_type) { case TransceiverFactory::PTT_method_VOX: @@ -221,7 +187,7 @@ HamlibTransceiver::HamlibTransceiver (int model_number case TransceiverFactory::PTT_method_DTR: case TransceiverFactory::PTT_method_RTS: - if (!ptt_port.isEmpty () && ptt_port != "None" && ptt_port != cat_port) + if (!ptt_port.isEmpty ()) { #if defined (WIN32) set_conf ("ptt_pathname", ("\\\\.\\" + ptt_port).toLatin1 ().data ()); @@ -239,6 +205,100 @@ HamlibTransceiver::HamlibTransceiver (int model_number set_conf ("ptt_type", "RTS"); } } +} + +HamlibTransceiver::HamlibTransceiver (int model_number, TransceiverFactory::ParameterPack const& params) + : PollingTransceiver {params.poll_interval} + , rig_ {rig_init (model_number)} + , back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == params.audio_source} + , is_dummy_ {RIG_MODEL_DUMMY == model_number} + , reversed_ {false} + , split_query_works_ {true} + , tickle_hamlib_ {false} + , get_vfo_works_ {true} +{ + if (!rig_) + { + throw error {tr ("Hamlib initialisation error")}; + } + + // rig_->state.obj = this; + + if (RIG_MODEL_DUMMY != model_number) + { + switch (rig_->caps->port_type) + { + case RIG_PORT_SERIAL: + if (!params.serial_port.isEmpty ()) + { + set_conf ("rig_pathname", params.serial_port.toLatin1 ().data ()); + } + break; + + case RIG_PORT_NETWORK: + if (!params.network_port.isEmpty ()) + { + set_conf ("rig_pathname", params.network_port.toLatin1 ().data ()); + } + break; + + default: + throw error {tr ("Unsupported CAT type")}; + break; + } + + set_conf ("serial_speed", QByteArray::number (params.baud).data ()); + set_conf ("data_bits", TransceiverFactory::seven_data_bits == params.data_bits ? "7" : "8"); + set_conf ("stop_bits", TransceiverFactory::one_stop_bit == params.stop_bits ? "1" : "2"); + + switch (params.handshake) + { + case TransceiverFactory::handshake_none: set_conf ("serial_handshake", "None"); break; + case TransceiverFactory::handshake_XonXoff: set_conf ("serial_handshake", "XONXOFF"); break; + case TransceiverFactory::handshake_hardware: set_conf ("serial_handshake", "Hardware"); break; + } + + if (params.force_line_control) + { + set_conf ("dtr_state", params.dtr_high ? "ON" : "OFF"); + set_conf ("rts_state", params.rts_high ? "ON" : "OFF"); + } + } + + switch (params.ptt_type) + { + case TransceiverFactory::PTT_method_VOX: + set_conf ("ptt_type", "None"); + break; + + case TransceiverFactory::PTT_method_CAT: + // Use the default PTT_TYPE for the rig (defined in the Hamlib + // rig back-end capabilities). + break; + + case TransceiverFactory::PTT_method_DTR: + case TransceiverFactory::PTT_method_RTS: + if (!params.ptt_port.isEmpty () + && params.ptt_port != "None" + && (RIG_MODEL_DUMMY == model_number + || params.ptt_port != params.serial_port)) + { +#if defined (WIN32) + set_conf ("ptt_pathname", ("\\\\.\\" + params.ptt_port).toLatin1 ().data ()); +#else + set_conf ("ptt_pathname", params.ptt_port.toLatin1 ().data ()); +#endif + } + + if (TransceiverFactory::PTT_method_DTR == params.ptt_type) + { + set_conf ("ptt_type", "DTR"); + } + else + { + set_conf ("ptt_type", "RTS"); + } + } // Make Icom CAT split commands less glitchy set_conf ("no_xchg", "1"); @@ -255,20 +315,14 @@ void HamlibTransceiver::error_check (int ret_code, QString const& doing) const { if (RIG_OK != ret_code) { -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::error_check: error:" << rigerror (ret_code); -#endif - + TRACE_CAT_POLL ("error:" << rigerror (ret_code)); throw error {tr ("Hamlib error: %1 while %2").arg (rigerror (ret_code)).arg (doing)}; } } void HamlibTransceiver::do_start () { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_start rig:" << QString::fromLatin1 (rig_->caps->mfg_name).trimmed () + ' ' - + QString::fromLatin1 (rig_->caps->model_name).trimmed (); -#endif + TRACE_CAT (QString::fromLatin1 (rig_->caps->mfg_name).trimmed () << QString::fromLatin1 (rig_->caps->model_name).trimmed ()); error_check (rig_open (rig_.data ()), tr ("opening connection to rig")); @@ -286,7 +340,7 @@ void HamlibTransceiver::do_start () } if (!is_dummy_ && rig_->caps->set_split_vfo) // if split is possible - // do some extra setup + // do some extra setup { freq_t f1; freq_t f2; @@ -301,67 +355,39 @@ void HamlibTransceiver::do_start () // VFO is selected or if SPLIT is selected so we have to simply // assume it is as when we started by setting at open time right // here. We also gather/set other initial state. -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_freq"; -#endif error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting current frequency")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_freq current frequency =" << f1; -#endif + TRACE_CAT ("current frequency =" << f1); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode"; -#endif error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w; -#endif + TRACE_CAT ("current mode =" << rig_strrmode (m) << "bw =" << w); if (!rig_->caps->set_vfo) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_vfo_op TOGGLE"; -#endif + TRACE_CAT ("rig_vfo_op TOGGLE"); error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs")); } else { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_set_vfo to other VFO"; -#endif + TRACE_CAT ("rig_set_vfo to other VFO"); error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB), tr ("setting current VFO")); } -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_freq other frequency"; -#endif error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f2), tr ("getting other VFO frequency")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_freq other frequency =" << f2; -#endif + TRACE_CAT ("rig_get_freq other frequency =" << f2); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode other VFO"; -#endif error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &mb, &wb), tr ("getting other VFO mode")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode other mode =" << rig_strrmode (mb) << "bw =" << wb; -#endif + TRACE_CAT ("rig_get_mode other mode =" << rig_strrmode (mb) << "bw =" << wb); update_other_frequency (f2); if (!rig_->caps->set_vfo) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_vfo_op TOGGLE"; -#endif + TRACE_CAT ("rig_vfo_op TOGGLE"); error_check (rig_vfo_op (rig_.data (), RIG_VFO_CURR, RIG_OP_TOGGLE), tr ("exchanging VFOs")); } else { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_set_vfo A/MAIN"; -#endif + TRACE_CAT ("rig_set_vfo A/MAIN"); error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO")); } @@ -371,28 +397,16 @@ void HamlibTransceiver::do_start () } else { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_freq"; -#endif error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f1), tr ("getting frequency")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_freq frequency =" << f1; -#endif + TRACE_CAT ("rig_get_freq frequency =" << f1); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode"; -#endif error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting mode")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w; -#endif + TRACE_CAT ("rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w); update_rx_frequency (f1); } -#if WSJT_TRACE_CAT - // qDebug () << "HamlibTransceiver::init_rig rig_set_split_vfo split off"; -#endif + // TRACE_CAT ("rig_set_split_vfo split off"); // error_check (rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, RIG_SPLIT_OFF, RIG_VFO_CURR), tr ("setting split off")); // update_split (false); } @@ -402,26 +416,16 @@ void HamlibTransceiver::do_start () if (get_vfo_works_ && rig_->caps->get_vfo) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_vfo current VFO"; -#endif error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_vfo current VFO = " << rig_strvfo (v); -#endif + TRACE_CAT ("rig_get_vfo current VFO = " << rig_strvfo (v)); } reversed_ = RIG_VFO_B == v; if (!(rig_->caps->targetable_vfo & (RIG_TARGETABLE_MODE | RIG_TARGETABLE_PURE))) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode"; -#endif error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current mode")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w; -#endif + TRACE_CAT ("rig_get_mode current mode =" << rig_strrmode (m) << "bw =" << w); } } update_mode (map_mode (m)); @@ -429,23 +433,38 @@ void HamlibTransceiver::do_start () tickle_hamlib_ = true; + if (is_dummy_ && dummy_frequency_) + { + // return to where last dummy instance was + // TODO: this is going to break down if multiple dummy rigs are used + rig_set_freq (rig_.data (), RIG_VFO_CURR, dummy_frequency_); + update_rx_frequency (dummy_frequency_); + if (RIG_MODE_NONE != dummy_mode_) + { + rig_set_mode (rig_.data (), RIG_VFO_CURR, dummy_mode_, RIG_PASSBAND_NORMAL); + update_mode (map_mode (dummy_mode_)); + } + } + poll (); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::init_rig exit" << state () << "reversed =" << reversed_; -#endif + TRACE_CAT ("exit" << state () << "reversed =" << reversed_); } void HamlibTransceiver::do_stop () { + if (is_dummy_) + { + rig_get_freq (rig_.data (), RIG_VFO_CURR, &dummy_frequency_); + pbwidth_t width; + rig_get_mode (rig_.data (), RIG_VFO_CURR, &dummy_mode_, &width); + } if (rig_) { rig_close (rig_.data ()); } -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_stop: state:" << state () << "reversed =" << reversed_; -#endif + TRACE_CAT ("state:" << state () << "reversed =" << reversed_); } auto HamlibTransceiver::get_vfos () const -> std::tuple @@ -453,13 +472,8 @@ auto HamlibTransceiver::get_vfos () const -> std::tuple if (get_vfo_works_ && rig_->caps->get_vfo) { vfo_t v; -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::get_vfos rig_get_vfo"; -#endif error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::get_vfos rig_get_vfo VFO = " << rig_strvfo (v); -#endif + TRACE_CAT ("rig_get_vfo VFO = " << rig_strvfo (v)); reversed_ = RIG_VFO_B == v; } @@ -469,57 +483,41 @@ auto HamlibTransceiver::get_vfos () const -> std::tuple // frequency if split since these type of radios can only // support this way around -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::get_vfos rig_set_vfo VFO = A/MAIN"; -#endif + TRACE_CAT ("rig_set_vfo VFO = A/MAIN"); error_check (rig_set_vfo (rig_.data (), rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN), tr ("setting current VFO")); } // else only toggle available but both VFOs should be substitutable auto rx_vfo = rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN; - auto tx_vfo = state ().split () ? (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB) : rx_vfo; + auto tx_vfo = !is_dummy_ && state ().split () + ? (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB) + : rx_vfo; if (reversed_) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::get_vfos reversing VFOs"; -#endif + TRACE_CAT ("reversing VFOs"); std::swap (rx_vfo, tx_vfo); } -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::get_vfos RX VFO = " << rig_strvfo (rx_vfo) << " TX VFO = " << rig_strvfo (tx_vfo); -#endif - + TRACE_CAT ("RX VFO = " << rig_strvfo (rx_vfo) << " TX VFO = " << rig_strvfo (tx_vfo)); return std::make_tuple (rx_vfo, tx_vfo); } void HamlibTransceiver::do_frequency (Frequency f, MODE m) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_frequency:" << f << "mode:" << m << "reversed:" << reversed_; -#endif + TRACE_CAT (f << "mode:" << m << "reversed:" << reversed_); - if (!is_dummy_) - { - // for the 1st time as a band change may cause a recalled mode - // to be set - error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency")); - } + // for the 1st time as a band change may cause a recalled mode to be + // set + error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency")); if (UNK != m) { do_mode (m, false); - } - if (!is_dummy_) - { // for the 2nd time because a mode change may have caused a // frequency change error_check (rig_set_freq (rig_.data (), RIG_VFO_CURR, f), tr ("setting frequency")); - } - if (UNK != m) - { // for the second time because some rigs change mode according // to frequency such as the TS-2000 auto mode setting do_mode (m, false); @@ -530,11 +528,10 @@ void HamlibTransceiver::do_frequency (Frequency f, MODE m) void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency:" << tx << "rationalise mode:" << rationalise_mode << "reversed:" << reversed_; -#endif + TRACE_CAT (tx << "rationalise mode:" << rationalise_mode << "reversed:" << reversed_); - if (!is_dummy_) + if (!is_dummy_) // split is meaning less if you can't + // see it { auto split = tx ? RIG_SPLIT_ON : RIG_SPLIT_OFF; update_split (tx); @@ -557,9 +554,7 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) // much we can do since the Hamlib Library needs this // call at least once to establish the Tx VFO. Best we // can do is only do this once per session. -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_vfo split =" << split; -#endif + TRACE_CAT ("rig_set_split_vfo split =" << split); auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo); if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc)) { @@ -575,12 +570,7 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) tickle_hamlib_ = false; } -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_freq"; -#endif - hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo); - // do this before setting the mode because changing band may // recall the last mode used on the target band error_check (rig_set_split_freq (rig_.data (), RIG_VFO_CURR, tx), tr ("setting split TX frequency")); @@ -590,20 +580,13 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) rmode_t current_mode; pbwidth_t current_width; -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency rig_get_split_mode"; -#endif error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, ¤t_mode, ¤t_width), tr ("getting mode of split TX VFO")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width; -#endif + TRACE_CAT ("rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width); auto new_mode = map_mode (state ().mode ()); if (new_mode != current_mode) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_mode mode = " << rig_strrmode (new_mode); -#endif + TRACE_CAT ("rig_set_split_mode mode = " << rig_strrmode (new_mode)); error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode")); // do this again as setting the mode may change the frequency @@ -616,9 +599,7 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) // of split when you switch RX VFO (to set split mode above for // example). Also the Elecraft K3 will refuse to go to split // with certain VFO A/B mode combinations. -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_tx_frequency rig_set_split_vfo split =" << split; -#endif + TRACE_CAT ("rig_set_split_vfo split =" << split); auto rc = rig_set_split_vfo (rig_.data (), RIG_VFO_CURR, split, tx_vfo); if (tx || (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc)) { @@ -630,209 +611,136 @@ void HamlibTransceiver::do_tx_frequency (Frequency tx, bool rationalise_mode) // specific rig. error_check (rc, tr ("setting/unsetting split mode")); } - } - update_other_frequency (tx); + update_other_frequency (tx); + } } void HamlibTransceiver::do_mode (MODE mode, bool rationalise) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode:" << mode << "rationalise:" << rationalise; -#endif + TRACE_CAT (mode << "rationalise:" << rationalise); - if (!is_dummy_) + auto vfos = get_vfos (); + // auto rx_vfo = std::get<0> (vfos); + auto tx_vfo = std::get<1> (vfos); + + rmode_t current_mode; + pbwidth_t current_width; + + error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, ¤t_mode, ¤t_width), tr ("getting current VFO mode")); + TRACE_CAT ("rig_get_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width); + + auto new_mode = map_mode (mode); + if (new_mode != current_mode) { - auto vfos = get_vfos (); - // auto rx_vfo = std::get<0> (vfos); - auto tx_vfo = std::get<1> (vfos); + TRACE_CAT ("rig_set_mode mode = " << rig_strrmode (new_mode)); + error_check (rig_set_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting current VFO mode")); + } + + if (!is_dummy_ && state ().split () && rationalise) + { + error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, ¤t_mode, ¤t_width), tr ("getting split TX VFO mode")); + TRACE_CAT ("rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width); - rmode_t current_mode; - pbwidth_t current_width; - -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode rig_get_mode"; -#endif - error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, ¤t_mode, ¤t_width), tr ("getting current VFO mode")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode rig_get_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width; -#endif - - auto new_mode = map_mode (mode); if (new_mode != current_mode) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode rig_set_mode mode = " << rig_strrmode (new_mode); -#endif - error_check (rig_set_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting current VFO mode")); - } - - if (state ().split () && rationalise) - { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode rig_get_split_mode"; -#endif - error_check (rig_get_split_mode (rig_.data (), RIG_VFO_CURR, ¤t_mode, ¤t_width), tr ("getting split TX VFO mode")); -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode rig_get_split_mode mode = " << rig_strrmode (current_mode) << "bw =" << current_width; -#endif - - if (new_mode != current_mode) - { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_mode rig_set_split_mode mode = " << rig_strrmode (new_mode); -#endif - hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo); - error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode")); - } + TRACE_CAT ("rig_set_split_mode mode = " << rig_strrmode (new_mode)); + hamlib_tx_vfo_fixup fixup (rig_.data (), tx_vfo); + error_check (rig_set_split_mode (rig_.data (), RIG_VFO_CURR, new_mode, RIG_PASSBAND_NORMAL), tr ("setting split TX VFO mode")); } } - update_mode (mode); } void HamlibTransceiver::poll () { - if (is_dummy_) - { - // split with dummy is never reported since there is no rig - if (state ().split ()) - { - update_split (false); - } - } - else - { #if !WSJT_TRACE_CAT_POLLS #if defined (NDEBUG) - rig_set_debug (RIG_DEBUG_ERR); + rig_set_debug (RIG_DEBUG_ERR); #else - rig_set_debug (RIG_DEBUG_WARN); + rig_set_debug (RIG_DEBUG_WARN); #endif #endif - freq_t f; - rmode_t m; - pbwidth_t w; - split_t s; + freq_t f; + rmode_t m; + pbwidth_t w; + split_t s; - if (get_vfo_works_ && rig_->caps->get_vfo) + if (get_vfo_works_ && rig_->caps->get_vfo) + { + vfo_t v; + error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib + TRACE_CAT_POLL ("VFO =" << rig_strvfo (v)); + reversed_ = RIG_VFO_B == v; + } + + error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency")); + TRACE_CAT_POLL ("rig_get_freq frequency =" << f); + update_rx_frequency (f); + + if (!is_dummy_ && state ().split () && (rig_->caps->targetable_vfo & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE))) + { + // only read "other" VFO if in split, this allows rigs like + // FlexRadio to work in Kenwood TS-2000 mode despite them + // not having a FB; command + + // we can only probe current VFO unless rig supports reading + // the other one directly because we can't glitch the Rx + error_check (rig_get_freq (rig_.data () + , reversed_ + ? (rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN) + : (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB) + , &f), tr ("getting current VFO frequency")); + TRACE_CAT_POLL ("rig_get_freq other VFO =" << f); + update_other_frequency (f); + } + + error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current VFO mode")); + TRACE_CAT_POLL ("rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w); + update_mode (map_mode (m)); + + if (!is_dummy_ && rig_->caps->get_split_vfo && split_query_works_) + { + vfo_t v {RIG_VFO_NONE}; // so we can tell if it doesn't get updated :( + auto rc = rig_get_split_vfo (rig_.data (), RIG_VFO_CURR, &s, &v); + if (-RIG_OK == rc && RIG_SPLIT_ON == s) { -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_vfo"; -#endif - vfo_t v; - error_check (rig_get_vfo (rig_.data (), &v), tr ("getting current VFO")); // has side effect of establishing current VFO inside hamlib -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_vfo VFO = " << rig_strvfo (v); -#endif - - reversed_ = RIG_VFO_B == v; + TRACE_CAT_POLL ("rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v)); + update_split (true); + // if (RIG_VFO_A == v) + // { + // reversed_ = true; // not sure if this helps us here + // } } - -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_freq"; -#endif - error_check (rig_get_freq (rig_.data (), RIG_VFO_CURR, &f), tr ("getting current VFO frequency")); -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_freq frequency =" << f; -#endif - - update_rx_frequency (f); - - if (state ().split () && (rig_->caps->targetable_vfo & (RIG_TARGETABLE_FREQ | RIG_TARGETABLE_PURE))) + else if (-RIG_OK == rc) // not split { - // only read "other" VFO if in split, this allows rigs like - // FlexRadio to work in Kenwood TS-2000 mode despite them - // not having a FB; command - - // we can only probe current VFO unless rig supports reading - // the other one directly because we can't glitch the Rx -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_freq other VFO"; -#endif - error_check (rig_get_freq (rig_.data () - , reversed_ - ? (rig_->state.vfo_list & RIG_VFO_A ? RIG_VFO_A : RIG_VFO_MAIN) - : (rig_->state.vfo_list & RIG_VFO_B ? RIG_VFO_B : RIG_VFO_SUB) - , &f), tr ("getting current VFO frequency")); -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_freq other VFO =" << f; -#endif - - update_other_frequency (f); + TRACE_CAT_POLL ("rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v)); + update_split (false); } - -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_mode"; -#endif - error_check (rig_get_mode (rig_.data (), RIG_VFO_CURR, &m, &w), tr ("getting current VFO mode")); -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_mode mode =" << rig_strrmode (m) << "bw =" << w; -#endif - - update_mode (map_mode (m)); - - if (rig_->caps->get_split_vfo && split_query_works_) + else { -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_split_vfo"; -#endif - vfo_t v {RIG_VFO_NONE}; // so we can tell if it doesn't get updated :( - auto rc = rig_get_split_vfo (rig_.data (), RIG_VFO_CURR, &s, &v); - if (-RIG_OK == rc && RIG_SPLIT_ON == s) - { -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v); -#endif - - update_split (true); - // if (RIG_VFO_A == v) - // { - // reversed_ = true; // not sure if this helps us here - // } - } - else if (-RIG_OK == rc) // not split - { -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_split_vfo split = " << s << " VFO = " << rig_strvfo (v); -#endif - - update_split (false); - } - else - { - // Some rigs (Icom) don't have a way of reporting SPLIT - // mode - -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_split_vfo can't do on this rig"; -#endif - - // just report how we see it based on prior commands - split_query_works_ = false; - } + // Some rigs (Icom) don't have a way of reporting SPLIT + // mode + TRACE_CAT_POLL ("rig_get_split_vfo can't do on this rig"); + // just report how we see it based on prior commands + split_query_works_ = false; } + } - if (RIG_PTT_NONE != rig_->state.pttport.type.ptt && rig_->caps->get_ptt) + if (RIG_PTT_NONE != rig_->state.pttport.type.ptt && rig_->caps->get_ptt) + { + ptt_t p; + auto rc = rig_get_ptt (rig_.data (), RIG_VFO_CURR, &p); + if (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc) // may fail if + // Net rig ctl and target doesn't + // support command { -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_ptt"; -#endif - ptt_t p; - auto rc = rig_get_ptt (rig_.data (), RIG_VFO_CURR, &p); - if (-RIG_ENAVAIL != rc && -RIG_ENIMPL != rc) // may fail if - // Net rig ctl and target doesn't - // support command - { - error_check (rc, tr ("getting PTT state")); -#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS - qDebug () << "HamlibTransceiver::poll rig_get_ptt PTT =" << p; -#endif - - update_PTT (!(RIG_PTT_OFF == p)); - } + error_check (rc, tr ("getting PTT state")); + TRACE_CAT_POLL ("rig_get_ptt PTT =" << p); + update_PTT (!(RIG_PTT_OFF == p)); } + } #if !WSJT_TRACE_CAT_POLLS #if WSJT_HAMLIB_TRACE @@ -847,32 +755,26 @@ void HamlibTransceiver::poll () rig_set_debug (RIG_DEBUG_WARN); #endif #endif - } } void HamlibTransceiver::do_ptt (bool on) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_ptt:" << on << state () << "reversed =" << reversed_; -#endif - + TRACE_CAT (on << state () << "reversed =" << reversed_); if (on) { if (RIG_PTT_NONE != rig_->state.pttport.type.ptt) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_ptt rig_set_ptt PTT = true"; -#endif - error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR, back_ptt_port_ ? RIG_PTT_ON_DATA : RIG_PTT_ON), tr ("setting PTT on")); + TRACE_CAT ("rig_set_ptt PTT = true"); + error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR + , RIG_PTT_RIG_MICDATA == rig_->caps->ptt_type && back_ptt_port_ + ? RIG_PTT_ON_DATA : RIG_PTT_ON), tr ("setting PTT on")); } } else { if (RIG_PTT_NONE != rig_->state.pttport.type.ptt) { -#if WSJT_TRACE_CAT - qDebug () << "HamlibTransceiver::do_ptt rig_set_ptt PTT = false"; -#endif + TRACE_CAT ("rig_set_ptt PTT = false"); error_check (rig_set_ptt (rig_.data (), RIG_VFO_CURR, RIG_PTT_OFF), tr ("setting PTT off")); } } diff --git a/HamlibTransceiver.hpp b/HamlibTransceiver.hpp index 86b1b4233..8e7f8d8fe 100644 --- a/HamlibTransceiver.hpp +++ b/HamlibTransceiver.hpp @@ -26,18 +26,8 @@ class HamlibTransceiver final public: static void register_transceivers (TransceiverFactory::Transceivers *); - explicit HamlibTransceiver (int model_number - , QString const& cat_port - , int cat_baud - , TransceiverFactory::DataBits cat_data_bits - , TransceiverFactory::StopBits cat_stop_bits - , TransceiverFactory::Handshake cat_handshake - , TransceiverFactory::LineControl cat_dtr_control - , TransceiverFactory::LineControl cat_rts_control - , TransceiverFactory::PTTMethod ptt_type - , TransceiverFactory::TXAudioSource back_ptt_port - , QString const& ptt_port - , int poll_interval = 0); + explicit HamlibTransceiver (int model_number, TransceiverFactory::ParameterPack const&); + explicit HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QString const& ptt_port); ~HamlibTransceiver (); private: @@ -63,6 +53,11 @@ class HamlibTransceiver final bool back_ptt_port_; bool is_dummy_; + // these are saved on destruction so we can start new instances + // where the last one left off + static freq_t dummy_frequency_; + static rmode_t dummy_mode_; + bool mutable reversed_; bool split_query_works_; diff --git a/OmniRigTransceiver.cpp b/OmniRigTransceiver.cpp index ce0c60630..b7a9a6adc 100644 --- a/OmniRigTransceiver.cpp +++ b/OmniRigTransceiver.cpp @@ -2,9 +2,10 @@ #include #include - #include +#include "qt_helpers.hpP" + #include "moc_OmniRigTransceiver.cpp" namespace @@ -47,12 +48,9 @@ auto OmniRigTransceiver::map_mode (OmniRig::RigParamX param) -> MODE { return FM; } - -#if WSJT_TRACE_CAT - qDebug () << "OmniRig map_mode unrecognized mode"; -#endif - - throw error {tr ("OmniRig: unrecognized mode")}; + TRACE_CAT ("unrecognized mode"); + throw_qstring (tr ("OmniRig: unrecognized mode")); + return UNK; } OmniRig::RigParamX OmniRigTransceiver::map_mode (MODE mode) @@ -115,10 +113,7 @@ OmniRigTransceiver::~OmniRigTransceiver () void OmniRigTransceiver::do_start () { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_start"; -#endif - + TRACE_CAT ("starting"); wrapped_->start (); CoInitializeEx (nullptr, 0 /*COINIT_APARTMENTTHREADED*/); // required because Qt only does this for GUI thread @@ -126,11 +121,8 @@ void OmniRigTransceiver::do_start () omni_rig_.reset (new OmniRig::OmniRigX {this}); if (omni_rig_->isNull ()) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_start: failed to start COM server"; -#endif - - throw error {tr ("Failed to start OmniRig COM server")}; + TRACE_CAT ("failed to start COM server"); + throw_qstring (tr ("Failed to start OmniRig COM server")); } // COM/OLE exceptions get signalled @@ -145,12 +137,8 @@ void OmniRigTransceiver::do_start () , SIGNAL (CustomReply (int, QVariant const&, QVariant const&)) , this, SLOT (handle_custom_reply (int, QVariant const&, QVariant const&))); -#if WSJT_TRACE_CAT - qDebug () - << "OmniRig s/w version:" << QString::number (omni_rig_->SoftwareVersion ()).toLocal8Bit () - << "i/f version:" << QString::number (omni_rig_->InterfaceVersion ()).toLocal8Bit () - ; -#endif + TRACE_CAT ("OmniRig s/w version:" << QString::number (omni_rig_->SoftwareVersion ()).toLocal8Bit () + << "i/f version:" << QString::number (omni_rig_->InterfaceVersion ()).toLocal8Bit ()); // fetch the interface of the RigX CoClass and instantiate a proxy object switch (rig_number_) @@ -172,7 +160,7 @@ void OmniRigTransceiver::do_start () // if (!port_->Lock ()) // try to take exclusive use of the OmniRig serial port for PTT // { - // throw error {tr ("Failed to get exclusive use of %1" from OmniRig").arg (ptt_type)}; + // throw_qstring (tr ("Failed to get exclusive use of %1" from OmniRig").arg (ptt_type)); // } // start off so we don't accidentally key the radio @@ -189,17 +177,19 @@ void OmniRigTransceiver::do_start () readable_params_ = rig_->ReadableParams (); writable_params_ = rig_->WriteableParams (); -#if WSJT_TRACE_CAT - qDebug () - << QString ("OmniRig initial rig type: %1 readable params = 0x%2 writable params = 0x%3 for rig %4") + TRACE_CAT (QString {"OmniRig initial rig type: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"} .arg (rig_->RigType ()) .arg (readable_params_, 8, 16, QChar ('0')) .arg (writable_params_, 8, 16, QChar ('0')) - .arg (rig_number_).toLocal8Bit () - ; -#endif + .arg (rig_number_).toLocal8Bit ()); - QTimer::singleShot (5000, this, SLOT (online_check ())); + rig_->GetRxFrequency (); + if (OmniRig::ST_ONLINE != rig_->Status ()) + { + throw_qstring ("OmniRig exception: " + rig_->StatusStr ()); + } + + init_rig (); } void OmniRigTransceiver::do_stop () @@ -209,18 +199,11 @@ void OmniRigTransceiver::do_stop () // port_->Unlock (); // release serial port port_->clear (); } - rig_->clear (); - omni_rig_->clear (); - CoUninitialize (); - wrapped_->stop (); - -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_stop"; -#endif + TRACE_CAT ("stopped"); } void OmniRigTransceiver::online_check () @@ -248,20 +231,15 @@ void OmniRigTransceiver::online_check () void OmniRigTransceiver::init_rig () { + update_rx_frequency (rig_->GetRxFrequency ()); if (state ().split ()) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::init_rig: set split"; -#endif - + TRACE_CAT ("set split"); rig_->SetSplitMode (state ().frequency (), state ().tx_frequency ()); } else { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::init_rig: set simplex"; -#endif - + TRACE_CAT ("set simplex"); rig_->SetSimplexMode (state ().frequency ()); } } @@ -279,18 +257,13 @@ void OmniRigTransceiver::do_sync (bool force_signal) void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString desc, QString help) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::handle_COM_exception:" << QString::number (code) + " at " + source + ": " + desc + " (" + help + ')'; -#endif - - throw error {tr ("OmniRig COM/OLE error: %1 at %2: %3 (%4)").arg (QString::number (code)).arg (source). arg (desc). arg (help)}; + TRACE_CAT (QString::number (code) + " at " + source + ": " + desc + " (" + help + ')'); + throw_qstring (tr ("OmniRig COM/OLE error: %1 at %2: %3 (%4)").arg (QString::number (code)).arg (source). arg (desc). arg (help)); } void OmniRigTransceiver::handle_visible_change () { -#if WSJT_TRACE_CAT - qDebug () << "OmniRig visibility change: visibility =" << omni_rig_->DialogVisible (); -#endif + TRACE_CAT ("visibility change: visibility =" << omni_rig_->DialogVisible ()); } void OmniRigTransceiver::handle_rig_type_change (int rig_number) @@ -299,17 +272,11 @@ void OmniRigTransceiver::handle_rig_type_change (int rig_number) { readable_params_ = rig_->ReadableParams (); writable_params_ = rig_->WriteableParams (); - -#if WSJT_TRACE_CAT - qDebug () - << QString ("OmniRig rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4") + TRACE_CAT (QString {"OmniRig rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"} .arg (rig_->RigType ()) .arg (readable_params_, 8, 16, QChar ('0')) .arg (writable_params_, 8, 16, QChar ('0')) - .arg (rig_number).toLocal8Bit () - ; -#endif - + .arg (rig_number).toLocal8Bit ()); offline ("OmniRig rig changed"); } } @@ -318,11 +285,7 @@ void OmniRigTransceiver::handle_status_change (int rig_number) { if (rig_number_ == rig_number) { -#if WSJT_TRACE_CAT - qDebug () - << QString ("OmniRig status change: new status for rig %1 = ").arg (rig_number).toLocal8Bit () << rig_->StatusStr ().toLocal8Bit (); -#endif - + TRACE_CAT (QString {"OmniRig status change: new status for rig %1 = "}.arg (rig_number).toLocal8Bit () << rig_->StatusStr ().toLocal8Bit ()); if (OmniRig::ST_ONLINE != rig_->Status ()) { QTimer::singleShot (5000, this, SLOT (online_check ())); @@ -347,24 +310,16 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params) { if (rig_number_ == rig_number) { -#if WSJT_TRACE_CAT - qDebug () - << QString ("OmniRig params change: params = 0x%1 for rig %2") + TRACE_CAT (QString {"OmniRig params change: params = 0x%1 for rig %2"} .arg (params, 8, 16, QChar ('0')) .arg (rig_number).toLocal8Bit () - << "state before:" << state () - ; -#endif - + << "state before:" << state ()); starting_ = false; - TransceiverState old_state {state ()}; auto need_frequency = false; - // state_.online = true; // sometimes we don't get an initial // // OmniRig::ST_ONLINE status change // // event - if (params & OmniRig::PM_VFOAA) { update_split (false); @@ -430,7 +385,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params) update_other_frequency (rig_->FreqB ()); } } - if (need_frequency) { if (readable_params_ & OmniRig::PM_FREQA) @@ -461,7 +415,6 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params) { update_rx_frequency (rig_->Freq ()); } - if (params & OmniRig::PM_PITCH) { } @@ -551,12 +504,7 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params) update_complete (); send_update_signal_ = false; } - -#if WSJT_TRACE_CAT - qDebug () - << "OmniRig params change: state after:" << state () - ; -#endif + TRACE_CAT ("OmniRig params change: state after:" << state ()); } } @@ -567,30 +515,19 @@ void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& co if (rig_number_ == rig_number) { -#if WSJT_TRACE_CAT - qDebug () - << "OmniRig custom command" << command.toString ().toLocal8Bit () - << "with reply" << reply.toString ().toLocal8Bit () - << QString ("for rig %1").arg (rig_number).toLocal8Bit () - ; - - qDebug () << "OmniRig rig number:" << rig_number_ << ':' << state (); -#endif + TRACE_CAT ("OmniRig custom command" << command.toString ().toLocal8Bit () + << "with reply" << reply.toString ().toLocal8Bit () + << QString ("for rig %1").arg (rig_number).toLocal8Bit ()); + TRACE_CAT ("OmniRig rig number:" << rig_number_ << ':' << state ()); } } void OmniRigTransceiver::do_ptt (bool on) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_ptt:" << on << state (); -#endif - + TRACE_CAT (on << state ()); if (use_for_ptt_ && TransceiverFactory::PTT_method_CAT == ptt_type_) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_ptt: set PTT"; -#endif - + TRACE_CAT ("set PTT"); rig_->SetTx (on ? OmniRig::PM_TX : OmniRig::PM_RX); } else @@ -599,33 +536,23 @@ void OmniRigTransceiver::do_ptt (bool on) { if (TransceiverFactory::PTT_method_RTS == ptt_type_) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_ptt: set RTS"; -#endif + TRACE_CAT ("set RTS"); port_->SetRts (on); } else // "DTR" { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_ptt: set DTR"; -#endif - + TRACE_CAT ("set DTR"); port_->SetDtr (on); } } else { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_ptt: set PTT using basic transceiver"; -#endif - + TRACE_CAT ("set PTT using basic transceiver"); wrapped_->ptt (on); } - if (state ().ptt () != on) { update_PTT (on); - // no need for this as currently update_PTT() does it for us // update_complete (); } @@ -634,15 +561,11 @@ void OmniRigTransceiver::do_ptt (bool on) void OmniRigTransceiver::do_frequency (Frequency f, MODE m) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_frequency:" << f << state (); -#endif - + TRACE_CAT (f << state ()); if (UNK != m) { do_mode (m, false); } - if (OmniRig::PM_FREQ & writable_params_) { rig_->SetFreq (f); @@ -660,40 +583,28 @@ void OmniRigTransceiver::do_frequency (Frequency f, MODE m) } else { - throw error {tr ("OmniRig: don't know how to set rig frequency")}; + throw_qstring (tr ("OmniRig: don't know how to set rig frequency")); } } void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode */) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_tx_frequency:" << tx << state (); -#endif - + TRACE_CAT (tx << state ()); bool split {tx != 0}; - if (split) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_tx_frequency: set SPLIT mode on"; -#endif - + TRACE_CAT ("set SPLIT mode on"); rig_->SetSplitMode (state ().frequency (), tx); update_other_frequency (tx); update_split (true); } else { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_tx_frequency: set SPLIT mode off"; -#endif - + TRACE_CAT ("set SPLIT mode off"); rig_->SetSimplexMode (state ().frequency ()); update_split (false); } - bool notify {false}; - if (readable_params_ & OmniRig::PM_FREQ || !(readable_params_ & (OmniRig::PM_FREQA | OmniRig::PM_FREQB))) { update_other_frequency (tx); // async updates won't return this @@ -702,18 +613,13 @@ void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode // "back" VFO on rig notify = true; } - if (!((OmniRig::PM_VFOAB | OmniRig::PM_VFOBA | OmniRig::PM_SPLITON) & readable_params_)) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_tx_frequency: setting SPLIT manually"; -#endif - + TRACE_CAT ("setting SPLIT manually"); update_split (split); // we can't read it so just set and // hope op doesn't change it notify = true; } - if (notify) { update_complete (); @@ -722,14 +628,9 @@ void OmniRigTransceiver::do_tx_frequency (Frequency tx, bool /* rationalise_mode void OmniRigTransceiver::do_mode (MODE mode, bool /* rationalise */) { -#if WSJT_TRACE_CAT - qDebug () << "OmniRigTransceiver::do_mode:" << mode << state (); -#endif - + TRACE_CAT (mode << state ()); // TODO: G4WJS OmniRig doesn't seem to have any capability of tracking/setting VFO B mode - auto mapped = map_mode (mode); - if (mapped & writable_params_) { rig_->SetMode (mapped); diff --git a/PollingTransceiver.cpp b/PollingTransceiver.cpp index d00783dcc..0f16bb8ae 100644 --- a/PollingTransceiver.cpp +++ b/PollingTransceiver.cpp @@ -6,96 +6,48 @@ #include #include -#include "pimpl_impl.hpp" - -#include "moc_PollingTransceiver.cpp" - namespace { unsigned const polls_to_stabilize {3}; } -// Internal implementation of the PollingTransceiver class. -class PollingTransceiver::impl final - : public QObject -{ - Q_OBJECT; - -public: - impl (PollingTransceiver * self, int poll_interval) - : QObject {self} - , self_ {self} - , interval_ {poll_interval} - , poll_timer_ {nullptr} - , retries_ {0} - { - } - -private: - impl (impl const&) = delete; - impl& operator = (impl const&) = delete; - - void start_timer () - { - if (interval_) - { - if (!poll_timer_) - { - poll_timer_ = new QTimer {this}; // pass ownership to QObject which handles destruction for us - - connect (poll_timer_, &QTimer::timeout, this, &PollingTransceiver::impl::handle_timeout); - } - poll_timer_->start (interval_); - } - } - - void stop_timer () - { - if (poll_timer_) - { - poll_timer_->stop (); - } - } - - Q_SLOT void handle_timeout (); - - PollingTransceiver * self_; // our owner so we can call methods - int interval_; // polling interval in milliseconds - QTimer * poll_timer_; - - // keep a record of the last state signalled so we can elide - // duplicate updates - Transceiver::TransceiverState last_signalled_state_; - - // keep a record of expected state so we can compare with actual - // updates to determine when state changes have bubbled through - Transceiver::TransceiverState next_state_; - - unsigned retries_; // number of incorrect polls left - - friend class PollingTransceiver; -}; - -#include "PollingTransceiver.moc" - - PollingTransceiver::PollingTransceiver (int poll_interval) - : m_ {this, poll_interval} + : interval_ {poll_interval * 1000} + , poll_timer_ {nullptr} + , retries_ {0} { } -PollingTransceiver::~PollingTransceiver () +void PollingTransceiver::start_timer () { + if (interval_) + { + if (!poll_timer_) + { + poll_timer_ = new QTimer {this}; // pass ownership to QObject which handles destruction for us + + connect (poll_timer_, &QTimer::timeout, this, &PollingTransceiver::handle_timeout); + } + poll_timer_->start (interval_); + } +} + +void PollingTransceiver::stop_timer () +{ + if (poll_timer_) + { + poll_timer_->stop (); + } } void PollingTransceiver::do_post_start () { - m_->start_timer (); - if (!m_->next_state_.online ()) + start_timer (); + if (!next_state_.online ()) { // remember that we are expecting to go online - m_->next_state_.online (true); - m_->retries_ = polls_to_stabilize; + next_state_.online (true); + retries_ = polls_to_stabilize; } } @@ -103,7 +55,7 @@ void PollingTransceiver::do_post_stop () { // not much point waiting for rig to go offline since we are ceasing // polls - m_->stop_timer (); + stop_timer (); } void PollingTransceiver::do_post_frequency (Frequency f, MODE m) @@ -111,55 +63,55 @@ void PollingTransceiver::do_post_frequency (Frequency f, MODE m) // take care not to set the expected next mode to unknown since some // callers use mode == unknown to signify that they do not know the // mode and don't care - if (m_->next_state_.frequency () != f || (m != UNK && m_->next_state_.mode () != m)) + if (next_state_.frequency () != f || (m != UNK && next_state_.mode () != m)) { // update expected state with new frequency and set poll count - m_->next_state_.frequency (f); + next_state_.frequency (f); if (m != UNK) { - m_->next_state_.mode (m); + next_state_.mode (m); } - m_->retries_ = polls_to_stabilize; + retries_ = polls_to_stabilize; } } void PollingTransceiver::do_post_tx_frequency (Frequency f, bool /* rationalize */) { - if (m_->next_state_.tx_frequency () != f) + if (next_state_.tx_frequency () != f) { // update expected state with new TX frequency and set poll // count - m_->next_state_.tx_frequency (f); - m_->next_state_.split (f); // setting non-zero TX frequency means split - m_->retries_ = polls_to_stabilize; + next_state_.tx_frequency (f); + next_state_.split (f); // setting non-zero TX frequency means split + retries_ = polls_to_stabilize; } } void PollingTransceiver::do_post_mode (MODE m, bool /*rationalize_mode*/) { // we don't ever expect mode to goto to unknown - if (m != UNK && m_->next_state_.mode () != m) + if (m != UNK && next_state_.mode () != m) { // update expected state with new mode and set poll count - m_->next_state_.mode (m); - m_->retries_ = polls_to_stabilize; + next_state_.mode (m); + retries_ = polls_to_stabilize; } } void PollingTransceiver::do_post_ptt (bool p) { - if (m_->next_state_.ptt () != p) + if (next_state_.ptt () != p) { // update expected state with new PTT and set poll count - m_->next_state_.ptt (p); - m_->retries_ = polls_to_stabilize; + next_state_.ptt (p); + retries_ = 0; // fast feedback on PTT } } bool PollingTransceiver::do_pre_update () { // if we are holding off a change then withhold the signal - if (m_->retries_ && state () != m_->next_state_) + if (retries_ && state () != next_state_) { return false; } @@ -175,10 +127,10 @@ void PollingTransceiver::do_sync (bool force_signal) // or, hasn't become what we expected after polls_to_stabilize // polls. Unsolicited changes will be signalled immediately unless // they intervene in a expected sequence where they will be delayed. - if (m_->retries_) + if (retries_) { - --m_->retries_; - if (force_signal || state () == m_->next_state_ || !m_->retries_) + --retries_; + if (force_signal || state () == next_state_ || !retries_) { // our client wants a signal regardless // or the expected state has arrived @@ -186,7 +138,7 @@ void PollingTransceiver::do_sync (bool force_signal) force_signal = true; } } - else if (force_signal || state () != m_->last_signalled_state_) + else if (force_signal || state () != last_signalled_state_) { // here is the normal passive polling path // either our client has requested a state update regardless of change @@ -197,14 +149,14 @@ void PollingTransceiver::do_sync (bool force_signal) if (force_signal) { // reset everything, record and signal the current state - m_->retries_ = 0; - m_->next_state_ = state (); - m_->last_signalled_state_ = state (); + retries_ = 0; + next_state_ = state (); + last_signalled_state_ = state (); update_complete (); } } -void PollingTransceiver::impl::handle_timeout () +void PollingTransceiver::handle_timeout () { QString message; @@ -212,7 +164,7 @@ void PollingTransceiver::impl::handle_timeout () // inform our parent of the failure via the offline() message try { - self_->do_sync (false); + do_sync (false); } catch (std::exception const& e) { @@ -224,6 +176,6 @@ void PollingTransceiver::impl::handle_timeout () } if (!message.isEmpty ()) { - self_->offline (message); + offline (message); } } diff --git a/PollingTransceiver.hpp b/PollingTransceiver.hpp index a27b7d031..2ae523d14 100644 --- a/PollingTransceiver.hpp +++ b/PollingTransceiver.hpp @@ -5,7 +5,7 @@ #include "TransceiverBase.hpp" -#include "pimpl_h.hpp" +class QTimer; // // Polling Transceiver @@ -17,7 +17,7 @@ // // Implements the TransceiverBase post action interface and provides // the abstract poll() operation for sub-classes to implement. The -// pol operation is invoked every poll_interval milliseconds. +// poll operation is invoked every poll_interval seconds. // // Responsibilities // @@ -35,10 +35,7 @@ class PollingTransceiver Q_OBJECT; // for translation context protected: - explicit PollingTransceiver (int poll_interval); // in milliseconds - -public: - ~PollingTransceiver (); + explicit PollingTransceiver (int poll_interval); // in seconds protected: void do_sync (bool force_signal) override final; @@ -56,8 +53,23 @@ protected: bool do_pre_update () override final; private: - class impl; - pimpl m_; + void start_timer (); + void stop_timer (); + + Q_SLOT void handle_timeout (); + + int interval_; // polling interval in milliseconds + QTimer * poll_timer_; + + // keep a record of the last state signalled so we can elide + // duplicate updates + Transceiver::TransceiverState last_signalled_state_; + + // keep a record of expected state so we can compare with actual + // updates to determine when state changes have bubbled through + Transceiver::TransceiverState next_state_; + + unsigned retries_; // number of incorrect polls left }; #endif diff --git a/Transceiver.hpp b/Transceiver.hpp index 2048a3998..c0e91aeb2 100644 --- a/Transceiver.hpp +++ b/Transceiver.hpp @@ -122,9 +122,6 @@ public: Q_SLOT virtual void start () noexcept = 0; Q_SLOT virtual void stop () noexcept = 0; - // Ready to be destroyed. - Q_SIGNAL void finished () const; - // Set frequency in Hertz. Q_SLOT virtual void frequency (Frequency, MODE = UNK) noexcept = 0; @@ -148,6 +145,9 @@ public: // asynchronous status updates Q_SIGNAL void update (Transceiver::TransceiverState) const; Q_SIGNAL void failure (QString reason) const; + + // Ready to be destroyed. + Q_SIGNAL void finished () const; }; Q_DECLARE_METATYPE (Transceiver::TransceiverState); diff --git a/TransceiverBase.cpp b/TransceiverBase.cpp index 0db0bfb74..af4624f78 100644 --- a/TransceiverBase.cpp +++ b/TransceiverBase.cpp @@ -3,73 +3,38 @@ #include #include - -#include "pimpl_impl.hpp" +#include +#include +#include namespace { auto const unexpected = TransceiverBase::tr ("Unexpected rig error"); } -class TransceiverBase::impl final - : public QObject -{ - Q_OBJECT; - -public: - impl (TransceiverBase * parent) - : parent_ {parent} - { - connect (this, &TransceiverBase::impl::updated, this, &TransceiverBase::impl::update_complete, Qt::QueuedConnection); - } - - impl (impl const&) = delete; - impl& operator = (impl const&) = delete; - - Q_SIGNAL void updated (); - Q_SLOT void update_complete () - { - if (parent_->do_pre_update ()) - { - Q_EMIT parent_->update (state_); - } - } - - TransceiverBase * parent_; - TransceiverState state_; -}; - - -#include "TransceiverBase.moc" - -TransceiverBase::TransceiverBase () - : m_ {this} -{ -} - -TransceiverBase::~TransceiverBase () -{ -} - void TransceiverBase::start () noexcept { QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { - m_->state_.online (false); - - // ensure PTT isn't left set - do_ptt (false); - do_post_ptt (false); - + try + { + // try and ensure PTT isn't left set + do_ptt (false); + do_post_ptt (false); + } + catch (...) + { + // don't care about exceptions + } do_stop (); do_post_stop (); } do_start (); do_post_start (); - m_->state_.online (true); + state_.online (true); } catch (std::exception const& e) { @@ -90,17 +55,22 @@ void TransceiverBase::stop () noexcept QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { - m_->state_.online (false); - - // ensure PTT isn't left set - do_ptt (false); - do_post_ptt (false); + try + { + // try and ensure PTT isn't left set + do_ptt (false); + do_post_ptt (false); + } + catch (...) + { + // don't care about exceptions + } } - do_stop (); do_post_stop (); + state_.online (false); } catch (std::exception const& e) { @@ -125,7 +95,7 @@ void TransceiverBase::frequency (Frequency f, MODE m) noexcept QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { do_frequency (f, m); do_post_frequency (f, m); @@ -150,7 +120,7 @@ void TransceiverBase::tx_frequency (Frequency tx, bool rationalise_mode) noexcep QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { do_tx_frequency (tx, rationalise_mode); do_post_tx_frequency (tx, rationalise_mode); @@ -175,7 +145,7 @@ void TransceiverBase::mode (MODE m, bool rationalise) noexcept QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { do_mode (m, rationalise); do_post_mode (m, rationalise); @@ -200,7 +170,7 @@ void TransceiverBase::ptt (bool on) noexcept QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { do_ptt (on); do_post_ptt (on); @@ -225,7 +195,7 @@ void TransceiverBase::sync (bool force_signal) noexcept QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { do_sync (force_signal); } @@ -246,28 +216,28 @@ void TransceiverBase::sync (bool force_signal) noexcept void TransceiverBase::update_rx_frequency (Frequency rx) { - m_->state_.frequency (rx); + state_.frequency (rx); } void TransceiverBase::update_other_frequency (Frequency tx) { - m_->state_.tx_frequency (tx); + state_.tx_frequency (tx); } void TransceiverBase::update_split (bool state) { - m_->state_.split (state); + state_.split (state); } void TransceiverBase::update_mode (MODE m) { - m_->state_.mode (m); + state_.mode (m); } void TransceiverBase::update_PTT (bool state) { - auto prior = m_->state_.ptt (); - m_->state_.ptt (state); + auto prior = state_.ptt (); + state_.ptt (state); if (state != prior) { // always signal PTT changes because some MainWindow logic @@ -276,11 +246,19 @@ void TransceiverBase::update_PTT (bool state) } } +void TransceiverBase::updated () + { + if (do_pre_update ()) + { + Q_EMIT update (state_); + } + } + void TransceiverBase::update_complete () { - // Use a signal to ensure that the calling function completes before + // Use a timer to ensure that the calling function completes before // the Transceiver::update signal is triggered. - Q_EMIT m_->updated (); + QTimer::singleShot (0, this, SLOT (updated ())); } void TransceiverBase::offline (QString const& reason) @@ -288,16 +266,22 @@ void TransceiverBase::offline (QString const& reason) QString message; try { - if (m_->state_.online ()) + if (state_.online ()) { - m_->state_.online (false); - - // ensure PTT isn't left set - do_ptt (false); - do_post_ptt (false); + try + { + // try and ensure PTT isn't left set + do_ptt (false); + do_post_ptt (false); + } + catch (...) + { + // don't care about exceptions + } } do_stop (); do_post_stop (); + state_.online (false); } catch (std::exception const& e) { @@ -309,8 +293,3 @@ void TransceiverBase::offline (QString const& reason) } Q_EMIT failure (reason + '\n' + message); } - -auto TransceiverBase::state () const -> TransceiverState const& -{ - return m_->state_; -} diff --git a/TransceiverBase.hpp b/TransceiverBase.hpp index 2cb06d6ca..8430ad498 100644 --- a/TransceiverBase.hpp +++ b/TransceiverBase.hpp @@ -7,8 +7,6 @@ #include "Transceiver.hpp" -#include "pimpl_h.hpp" - // // Base Transceiver Implementation // @@ -60,12 +58,12 @@ class TransceiverBase : public Transceiver { + Q_OBJECT; + protected: - TransceiverBase (); + TransceiverBase () = default; public: - ~TransceiverBase (); - // // Implement the Transceiver abstract interface. // @@ -127,11 +125,25 @@ protected: void offline (QString const& reason); // and query state with this one - TransceiverState const& state () const; + TransceiverState const& state () const {return state_;} private: - class impl; - pimpl m_; + Q_SLOT void updated (); + + TransceiverState state_; }; +// some trace macros +#if WSJT_TRACE_CAT +#define TRACE_CAT(MSG) qDebug () << __PRETTY_FUNCTION__ << MSG +#else +#define TRACE_CAT(MSG) +#endif + +#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS +#define TRACE_CAT_POLL(MSG) qDebug () << __PRETTY_FUNCTION__ << MSG +#else +#define TRACE_CAT_POLL(MSG) +#endif + #endif diff --git a/TransceiverFactory.cpp b/TransceiverFactory.cpp index 9e774f93a..cfe58487e 100644 --- a/TransceiverFactory.cpp +++ b/TransceiverFactory.cpp @@ -94,50 +94,22 @@ bool TransceiverFactory::has_asynchronous_CAT (QString const& name) const return supported_transceivers ()[name].asynchronous_; } -std::unique_ptr TransceiverFactory::create (QString const& name - , QString const& cat_port - , int cat_baud - , DataBits cat_data_bits - , StopBits cat_stop_bits - , Handshake cat_handshake - , LineControl cat_dtr_control - , LineControl cat_rts_control - , PTTMethod ptt_type - , TXAudioSource ptt_use_data_ptt - , SplitMode split_mode - , QString const& ptt_port - , int poll_interval - , QThread * target_thread - ) +std::unique_ptr TransceiverFactory::create (ParameterPack const& params, QThread * target_thread) { std::unique_ptr result; - switch (supported_transceivers ()[name].model_number_) + switch (supported_transceivers ()[params.rig_name].model_number_) { case CommanderId: { // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , force_low - , force_low - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; + std::unique_ptr basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}}; if (target_thread) { basic_transceiver.get ()->moveToThread (target_thread); } // wrap the basic Transceiver object instance with a decorator object that talks to DX Lab Suite Commander - result.reset (new DXLabSuiteCommanderTransceiver {std::move (basic_transceiver), cat_port, PTT_method_CAT == ptt_type, poll_interval}); + result.reset (new DXLabSuiteCommanderTransceiver {std::move (basic_transceiver), params.network_port, PTT_method_CAT == params.ptt_type, params.poll_interval}); if (target_thread) { result.get ()->moveToThread (target_thread); @@ -148,28 +120,14 @@ std::unique_ptr TransceiverFactory::create (QString const& name case HRDId: { // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_control - , cat_rts_control - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; + std::unique_ptr basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}}; if (target_thread) { basic_transceiver.get ()->moveToThread (target_thread); } // wrap the basic Transceiver object instance with a decorator object that talks to ham Radio Deluxe - result.reset (new HRDTransceiver {std::move (basic_transceiver), cat_port, PTT_method_CAT == ptt_type, poll_interval}); + result.reset (new HRDTransceiver {std::move (basic_transceiver), params.network_port, PTT_method_CAT == params.ptt_type, params.poll_interval}); if (target_thread) { result.get ()->moveToThread (target_thread); @@ -181,28 +139,14 @@ std::unique_ptr TransceiverFactory::create (QString const& name case OmniRigOneId: { // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_control - , cat_rts_control - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; + std::unique_ptr basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}}; if (target_thread) { basic_transceiver.get ()->moveToThread (target_thread); } // wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig one - result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::One, ptt_type, ptt_port}); + result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::One, params.ptt_type, params.ptt_port}); if (target_thread) { result.get ()->moveToThread (target_thread); @@ -213,28 +157,14 @@ std::unique_ptr TransceiverFactory::create (QString const& name case OmniRigTwoId: { // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_control - , cat_rts_control - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; + std::unique_ptr basic_transceiver {new HamlibTransceiver {params.ptt_type, params.ptt_port}}; if (target_thread) { basic_transceiver.get ()->moveToThread (target_thread); } // wrap the basic Transceiver object instance with a decorator object that talks to OmniRig rig two - result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::Two, ptt_type, ptt_port}); + result.reset (new OmniRigTransceiver {std::move (basic_transceiver), OmniRigTransceiver::Two, params.ptt_type, params.ptt_port}); if (target_thread) { result.get ()->moveToThread (target_thread); @@ -244,20 +174,7 @@ std::unique_ptr TransceiverFactory::create (QString const& name #endif default: - result.reset (new HamlibTransceiver { - supported_transceivers ()[name].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_control - , cat_rts_control - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? cat_port : ptt_port - , poll_interval - }); + result.reset (new HamlibTransceiver {supported_transceivers ()[params.rig_name].model_number_, params}); if (target_thread) { result.get ()->moveToThread (target_thread); @@ -265,7 +182,7 @@ std::unique_ptr TransceiverFactory::create (QString const& name break; } - if (split_mode_emulate == split_mode) + if (split_mode_emulate == params.split_mode) { // wrap the Transceiver object instance with a decorator that emulates split mode result.reset (new EmulateSplitTransceiver {std::move (result)}); @@ -282,7 +199,6 @@ std::unique_ptr TransceiverFactory::create (QString const& name ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, DataBits); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, StopBits); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, Handshake); -ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, LineControl); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, PTTMethod); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, TXAudioSource); ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode); @@ -291,7 +207,6 @@ ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, DataBits); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, StopBits); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, Handshake); -ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, LineControl); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, PTTMethod); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, TXAudioSource); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, SplitMode); @@ -299,7 +214,6 @@ ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, SplitMode); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, DataBits); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, StopBits); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, Handshake); -ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, LineControl); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, PTTMethod); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, TXAudioSource); ENUM_CONVERSION_OPS_IMPL (TransceiverFactory, SplitMode); diff --git a/TransceiverFactory.hpp b/TransceiverFactory.hpp index 7de0273f0..7d0ad18a2 100644 --- a/TransceiverFactory.hpp +++ b/TransceiverFactory.hpp @@ -21,10 +21,7 @@ class TransceiverFactory : public QObject { Q_OBJECT; - Q_ENUMS (DataBits StopBits Handshake LineControl PTTMethod TXAudioSource SplitMode); - -private: - Q_DISABLE_COPY (TransceiverFactory); + Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode); public: // @@ -70,7 +67,6 @@ public: enum DataBits {seven_data_bits = 7, eight_data_bits}; enum StopBits {one_stop_bit = 1, two_stop_bits}; enum Handshake {handshake_none, handshake_XonXoff, handshake_hardware}; - enum LineControl {no_control, force_low, force_high}; enum PTTMethod {PTT_method_VOX, PTT_method_CAT, PTT_method_DTR, PTT_method_RTS}; enum TXAudioSource {TX_audio_source_front, TX_audio_source_rear}; enum SplitMode {split_mode_none, split_mode_rig, split_mode_emulate}; @@ -91,6 +87,47 @@ public: bool has_CAT_indirect_serial_PTT (QString const& name) const; // Can PTT via CAT port use DTR or RTS (OmniRig for example) bool has_asynchronous_CAT (QString const& name) const; // CAT asynchronous rather than polled + struct ParameterPack + { + QString rig_name; // from supported_transceivers () key + QString serial_port; // serial port device name or empty + QString network_port; // hostname:port or empty + int baud; + DataBits data_bits; + StopBits stop_bits; + Handshake handshake; + bool force_line_control; + bool dtr_high; // to power interface + bool rts_high; // to power interface + PTTMethod ptt_type; // "CAT" | "DTR" | "RTS" | "VOX" + TXAudioSource audio_source; // some rigs allow audio routing + // to Mic/Data connector + SplitMode split_mode; // how to support split TX mode + QString ptt_port; // serial port device name or special + // value "CAT" + int poll_interval; // in seconds for interfaces that + // require polling for state changes + + bool operator == (ParameterPack const& rhs) const + { + return rhs.rig_name == rig_name + && rhs.serial_port == serial_port + && rhs.network_port == network_port + && rhs.baud == baud + && rhs.data_bits == data_bits + && rhs.stop_bits == stop_bits + && rhs.handshake == handshake + && rhs.force_line_control == force_line_control + && rhs.dtr_high == dtr_high + && rhs.rts_high == rts_high + && rhs.ptt_type == ptt_type + && rhs.audio_source == audio_source + && rhs.split_mode == split_mode + && rhs.ptt_port == ptt_port + && rhs.poll_interval == poll_interval; + } + }; + // make a new Transceiver instance // // cat_port, cat_baud, cat_data_bits, cat_stop_bits, cat_handshake, @@ -100,26 +137,18 @@ public: // PTT port and to some extent ptt_type are independent of interface // type // - std::unique_ptr create (QString const& name // from supported_transceivers () key - , QString const& cat_port // serial port device name or empty - , int cat_baud - , DataBits cat_data_bits - , StopBits cat_stop_bits - , Handshake cat_handshake - , LineControl cat_dtr_control // to power interface - , LineControl cat_rts_control // to power inteface - , PTTMethod ptt_type // "CAT" | "DTR" | "RTS" | "VOX" - , TXAudioSource ptt_use_data_ptt // some rigs allow audio routing to Mic/Data connector - , SplitMode split_mode // how to support split TX mode - , QString const& ptt_port // serial port device name or special value "CAT" - , int poll_interval // in milliseconds for interfaces that require polling for parameter changes - , QThread * target_thread = nullptr - ); + std::unique_ptr create (ParameterPack const&, QThread * target_thread = nullptr); private: Transceivers transceivers_; }; +inline +bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFactory::ParameterPack const& rhs) +{ + return !(lhs == rhs); +} + // // boilerplate routines to make enum types useable and debuggable in // Qt @@ -135,7 +164,6 @@ Q_DECLARE_METATYPE (TransceiverFactory::SplitMode); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake); -ENUM_QDEBUG_OPS_DECL (TransceiverFactory, LineControl); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource); ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode); @@ -144,7 +172,6 @@ ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake); -ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, LineControl); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, PTTMethod); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, TXAudioSource); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode); @@ -152,7 +179,6 @@ ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, SplitMode); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, DataBits); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, StopBits); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, Handshake); -ENUM_CONVERSION_OPS_DECL (TransceiverFactory, LineControl); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, PTTMethod); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, TXAudioSource); ENUM_CONVERSION_OPS_DECL (TransceiverFactory, SplitMode); diff --git a/mainwindow.cpp b/mainwindow.cpp index 654cee80f..16103f9e6 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2131,7 +2131,7 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl // QString t3=t.mid(i1,i4); auto t3 = decodedtext.string (); auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts); - if(t4.size () <5) return; //Skip the rest if no decoded text + if(t4.size () < 6) return; //Skip the rest if no decoded text */ auto t3 = decodedtext.string (); auto t4 = t3.replace (" CQ DX ", " CQ_DX ").split (" ", QString::SkipEmptyParts); @@ -2141,8 +2141,14 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl QString hiscall; QString hisgrid; decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid); - if (!Radio::is_callsign (hiscall)) + if (!Radio::is_callsign (hiscall) // not interested if not from QSO partner + && !(t4.size () == 7 // unless it is of the form + && (t4.at (5) == m_baseCall // " 73" + || t4.at (5).startsWith (m_baseCall + '/') + || t4.at (5).endsWith ('/' + m_baseCall)) + && t4.at (6) == "73")) { + qDebug () << "Not processing message - hiscall:" << hiscall << "hisgrid:" << hisgrid; return; } @@ -2207,6 +2213,9 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl return; } + // prior DX call (possible QSO partner) + auto qso_partner_base_call = Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()); + auto base_call = Radio::base_callsign (hiscall); if (base_call != Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()) || base_call != hiscall) { @@ -2234,13 +2243,13 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl if(dtext.contains (" " + m_baseCall + " ") || dtext.contains ("/" + m_baseCall + " ") || dtext.contains (" " + m_baseCall + "/") - || firstcall == "DE") + || (firstcall == "DE" && ((t4.size () > 7 && t4.at(7) != "73") || t4.size () <= 7))) { if (t4.size () > 7 // enough fields for a normal msg and !gridOK (t4.at (7))) // but no grid on end of msg { QString r=t4.at (7); - if(r.mid(0,3)=="RRR") { + if(r.mid(0,3)=="RRR" || (r.toInt()==73)) { m_ntx=5; ui->txrb5->setChecked(true); if(ui->tabWidget->currentIndex()==1) { @@ -2264,16 +2273,19 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl m_ntx=7; ui->rbGenMsg->setChecked(true); } - } else if(r.toInt()==73) { - m_ntx=5; - ui->txrb5->setChecked(true); - if(ui->tabWidget->currentIndex()==1) { - ui->genMsg->setText(ui->tx5->currentText()); - m_ntx=7; - ui->rbGenMsg->setChecked(true); - } } - } else { + } + else if (t4.size () == 7 && t4.at (6) == "73") { + // 73 back to compound call holder + m_ntx=5; + ui->txrb5->setChecked(true); + if(ui->tabWidget->currentIndex()==1) { + ui->genMsg->setText(ui->tx5->currentText()); + m_ntx=7; + ui->rbGenMsg->setChecked(true); + } + } + else { m_ntx=2; ui->txrb2->setChecked(true); if(ui->tabWidget->currentIndex()==1) { @@ -2282,8 +2294,29 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl ui->rbGenMsg->setChecked(true); } } - } + else if (firstcall == "DE" && t4.size () == 8 && t4.at (7) == "73") { + if (base_call == qso_partner_base_call) { + // 73 back to compound call holder + m_ntx=5; + ui->txrb5->setChecked(true); + if(ui->tabWidget->currentIndex()==1) { + ui->genMsg->setText(ui->tx5->currentText()); + m_ntx=7; + ui->rbGenMsg->setChecked(true); + } + } + else { + // treat like a CQ/QRZ + m_ntx=1; + ui->txrb1->setChecked(true); + if(ui->tabWidget->currentIndex()==1) { + ui->genMsg->setText(ui->tx1->text()); + m_ntx=7; + ui->rbGenMsg->setChecked(true); + } + } + } else // myCall not in msg { m_ntx=1; diff --git a/qt_helpers.hpp b/qt_helpers.hpp index 1b57acb85..c4ac6944e 100644 --- a/qt_helpers.hpp +++ b/qt_helpers.hpp @@ -67,7 +67,7 @@ inline void throw_qstring (QString const& qs) { - throw std::runtime_error (qs.toLocal8Bit ().data ()); + throw std::runtime_error {qs.toLocal8Bit ().constData ()}; } QString font_as_stylesheet (QFont const&);