Various defect repairs and ambigous behaviour clarifications

A regression introduced in v1.5.0-rc1 where PTT on an alternate serial
port when using no CAT control is resolved.

A regression introduced  in v1.5.0-rc1 where the  network server field
was not being restored in the settings dialog has been resolved.

In settings the "Test PTT" button is now styled  by checked state.

The  "Test PTT"  button is  enabled without  needing click  "Test CAT"
first when no CAT rig control is selected.

Various parts of the settings dialog  are now disabled when no CAT rig
control is selected. These are the "Mode" group, the "Split Operation"
group and the "Monitor returns to last used frequency" check box. None
of  these have  any  visible impact  nor make  sense  without CAT  rig
control.

Initialization and teardown of rig  control internals has been revised
to avoid several problems related to timing and when switching between
different  CAT  settings. This  includes  improvements  in having  the
operating frequency restored  between sessions when not  using CAT rig
control.

The  initialization   of  OmniRig   connections  has   been  improved,
unfortunately it is  still possible to get an  exception when clicking
the  "Test  CAT" button  where  just  clicking  "OK" and  leaving  the
settings dialog will probably work.

Some unnecessary  CAT commands output  during direct rig  control have
been elided to reduce the level of traffic a little.

The handling of  some automatically generated free  text messages used
when the station is a type 2  compound callsign or is working a type 2
compound callsign has  been improved. This is related to  how a double
click  on  a  message  of  the   form  "DE  TI4/N0URE  73"  is  double
clicked. The  new behaviour depends  on whether the current  "DX Call"
matches the  call in the message.   This resolves the ambiguity  as to
whether this message  is a sign off  at the end of a  QSO with current
operator (a 73  message is generated) or a tail  end opportunity where
the message should be treated the same  as a CQ or QRZ message (WSJT-X
QSYs  to the  frequency, generates  messages and  selects message  one
ready to call).  This still  leaves some potential ambiguous behaviors
in  this complex  area but  selecting "Clear  DX call  and grid  after
logging" should resolve most of them.

Rig  control trace  messages have  been cleaned  up and  are now  more
helpful, less verbose and, tidier in the source code.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx-1.5@5297 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2015-04-26 16:26:54 +00:00
parent 2cb9b00492
commit 12663c1fa1
17 changed files with 869 additions and 1369 deletions

View File

@ -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 <QApplication>
#include <QMetaType>
#include <QList>
#include <QSettings>
#include <QAudioDeviceInfo>
#include <QAudioInput>
@ -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<QMetaObject::Connection> 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
@ -624,7 +593,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_;}
@ -638,7 +607,7 @@ bool Configuration::watchdog () const {return m_->watchdog_;}
bool Configuration::TX_messages () const {return m_->TX_messages_;}
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_;}
@ -650,7 +619,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)
{
@ -752,7 +721,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}
@ -976,7 +945,7 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
restart_sound_output_device_ = false;
enumerate_rigs ();
initialise_models ();
initialize_models ();
transceiver_thread_.start ();
@ -997,7 +966,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 ())
@ -1018,7 +987,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_);
@ -1040,25 +1009,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 ())
{
@ -1067,7 +1036,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 ());
@ -1207,20 +1176,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<TransceiverFactory::DataBits> ();
rig_params_.CAT_stop_bits_ = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value<TransceiverFactory::StopBits> ();
rig_params_.CAT_handshake_ = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value<TransceiverFactory::Handshake> ();
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<TransceiverFactory::PTTMethod> ();
rig_params_.TX_audio_source_ = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value<TransceiverFactory::TXAudioSource> ();
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<TransceiverFactory::DataBits> ();
rig_params_.stop_bits = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value<TransceiverFactory::StopBits> ();
rig_params_.handshake = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value<TransceiverFactory::Handshake> ();
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<TransceiverFactory::PTTMethod> ();
rig_params_.audio_source = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value<TransceiverFactory::TXAudioSource> ();
rig_params_.ptt_port = settings_->value ("PTTport").toString ();
data_mode_ = settings_->value ("DataMode", QVariant::fromValue (data_mode_none)).value<Configuration::DataMode> ();
prompt_to_log_ = settings_->value ("PromptToLog", false).toBool ();
insert_blank_ = settings_->value ("InsertBlank", false).toBool ();
@ -1231,8 +1200,8 @@ void Configuration::impl::read_settings ()
disable_TX_on_73_ = settings_->value ("73TxDisable", false).toBool ();
watchdog_ = settings_->value ("Runaway", false).toBool ();
TX_messages_ = settings_->value ("Tx2QSO", 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<TransceiverFactory::SplitMode> ();
rig_params_.poll_interval = settings_->value ("Polling", 0).toInt ();
rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
udp_server_name_ = settings_->value ("UDPServer", "localhost").toString ();
udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt ();
accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
@ -1254,8 +1223,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_)
@ -1292,13 +1261,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_);
@ -1309,12 +1278,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 ("UDPServer", udp_server_name_);
settings_->setValue ("UDPServerPort", udp_server_port_);
settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
@ -1346,11 +1315,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;
@ -1358,7 +1342,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));
@ -1369,7 +1353,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"
@ -1377,7 +1362,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;
@ -1393,16 +1377,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);
@ -1447,13 +1421,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<TransceiverFactory::PTTMethod> (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)
@ -1472,17 +1439,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<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ());
result.stop_bits = static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ());
result.handshake = static_cast<TransceiverFactory::Handshake> (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<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
result.ptt_port = ui_->PTT_port_combo_box->currentText ();
result.audio_source = static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ());
result.split_mode = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
return result;
}
void Configuration::impl::accept ()
{
// Called when OK button is clicked.
@ -1495,39 +1494,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<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ());
temp_rig_params.CAT_stop_bits_ = static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ());
temp_rig_params.CAT_handshake_ = static_cast<TransceiverFactory::Handshake> (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<TransceiverFactory::PTTMethod> (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<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ());
temp_rig_params.split_mode_ = static_cast<TransceiverFactory::SplitMode> (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
@ -1569,7 +1536,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.
@ -1711,7 +1678,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
@ -1873,19 +1840,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 */)
@ -2036,7 +2003,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"));
}
@ -2047,84 +2014,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<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ())
, static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ())
, static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ())
, DTR
, RTS
, static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ())
, static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ())
, static_cast<TransceiverFactory::SplitMode> (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<DataMode> (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<DataMode> (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
@ -2139,38 +2098,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<DataMode> (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)
@ -2187,7 +2114,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_);
}
}
@ -2198,14 +2127,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
@ -2226,6 +2155,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 ())
{
@ -2238,7 +2169,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<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
@ -2246,11 +2176,12 @@ void Configuration::impl::handle_transceiver_update (TransceiverState state)
else
{
// Follow the rig unless configuration has been changed.
split_mode_selected = static_cast<TransceiverFactory::SplitMode> (rig_params_.split_mode_);
split_mode_selected = static_cast<TransceiverFactory::SplitMode> (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_)
{
@ -2261,7 +2192,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;
@ -2271,8 +2202,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 ();
}
}
@ -2309,6 +2238,7 @@ void Configuration::impl::handle_transceiver_failure (QString reason)
#endif
close_rig ();
ui_->test_PTT_push_button->setChecked (false);
if (isVisible ())
{
@ -2323,15 +2253,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;
}
}
@ -2456,7 +2389,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)
@ -2476,27 +2409,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);

View File

@ -201,6 +201,7 @@ private:
pimpl<impl> m_;
};
Q_DECLARE_METATYPE (Configuration::DataMode);
Q_DECLARE_METATYPE (Configuration::Type2MsgGen);

View File

@ -1060,10 +1060,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.</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton:checked {
background-color: red;
border-style : outset;
border-width: 1px;
border-radius: 5px;
border-color: black;
min-width: 5em;
padding: 3px;
}</string>
</property>
<property name="text">
<string>Test PTT</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
@ -2223,12 +2237,12 @@ soundcard changes</string>
</connection>
</connections>
<buttongroups>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="PTT_method_button_group"/>
<buttongroup name="TX_mode_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_mode_button_group"/>
</buttongroups>
</ui>

View File

@ -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 ? "<command:5>CmdTX<parameters:0>" : "<command:5>CmdRX<parameters:0>");
@ -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 (("<command:10>CmdSetMode<parameters:%1>" + 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

View File

@ -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<HRDMessage> message {new (string) HRDMessage};
if (!write_to_port (reinterpret_cast<char const *> (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)

View File

@ -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<TransceiverFactory::Transceivers *> (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<vfo_t, vfo_t>
@ -453,13 +472,8 @@ auto HamlibTransceiver::get_vfos () const -> std::tuple<vfo_t, vfo_t>
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<vfo_t, vfo_t>
// 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, &current_mode, &current_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, &current_mode, &current_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, &current_mode, &current_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, &current_mode, &current_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, &current_mode, &current_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"));
}
}

View File

@ -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_;

View File

@ -2,9 +2,10 @@
#include <QTimer>
#include <QDebug>
#include <objbase.h>
#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);

View File

@ -6,96 +6,48 @@
#include <QString>
#include <QTimer>
#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);
}
}

View File

@ -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<impl> 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

View File

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

View File

@ -3,73 +3,38 @@
#include <exception>
#include <QString>
#include "pimpl_impl.hpp"
#include <QTimer>
#include <QThread>
#include <QDebug>
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_;
}

View File

@ -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<impl> 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

View File

@ -94,50 +94,22 @@ bool TransceiverFactory::has_asynchronous_CAT (QString const& name) const
return supported_transceivers ()[name].asynchronous_;
}
std::unique_ptr<Transceiver> 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<Transceiver> TransceiverFactory::create (ParameterPack const& params, QThread * target_thread)
{
std::unique_ptr<Transceiver> 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<TransceiverBase> 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<TransceiverBase> 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<Transceiver> TransceiverFactory::create (QString const& name
case HRDId:
{
// we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> 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<TransceiverBase> 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<Transceiver> TransceiverFactory::create (QString const& name
case OmniRigOneId:
{
// we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> 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<TransceiverBase> 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<Transceiver> TransceiverFactory::create (QString const& name
case OmniRigTwoId:
{
// we start with a dummy HamlibTransceiver object instance that can support direct PTT
std::unique_ptr<TransceiverBase> 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<TransceiverBase> 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<Transceiver> 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<Transceiver> 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<Transceiver> 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);

View File

@ -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<Transceiver> 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<Transceiver> 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);

View File

@ -2004,13 +2004,19 @@ 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
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 // "<our-call> 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;
}
@ -2079,6 +2085,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)
{
@ -2106,13 +2115,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) {
@ -2136,16 +2145,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) {
@ -2154,8 +2166,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;

View File

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