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&);