diff --git a/Configuration.cpp b/Configuration.cpp index e542fd987..d24c7bddf 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -1746,7 +1746,9 @@ bool Configuration::impl::open_rig () , static_cast (ui_->split_mode_button_group->checkedId ()) , ui_->PTT_port_combo_box->currentText () , ui_->CAT_poll_interval_spin_box->value () * 1000 - , &transceiver_thread_); + , data_path_ + , &transceiver_thread_ + ); // hook up Configuration transceiver control signals to Transceiver slots // diff --git a/HRDTransceiver.cpp b/HRDTransceiver.cpp index 523a38df8..c8a282f27 100644 --- a/HRDTransceiver.cpp +++ b/HRDTransceiver.cpp @@ -63,11 +63,16 @@ struct HRDMessage qint32 const HRDMessage::magic_1_value_ (0x1234ABCD); qint32 const HRDMessage::magic_2_value_ (0xABCD1234); -HRDTransceiver::HRDTransceiver (std::unique_ptr wrapped, QString const& server, bool use_for_ptt, int poll_interval) +HRDTransceiver::HRDTransceiver (std::unique_ptr wrapped + , QString const& server + , bool use_for_ptt + , int poll_interval + , QDir const& data_path) : PollingTransceiver {poll_interval} , wrapped_ {std::move (wrapped)} , use_for_ptt_ {use_for_ptt} , server_ {server} + , data_path_ {data_path} , hrd_ {0} , protocol_ {none} , current_radio_ {0} @@ -150,11 +155,25 @@ void HRDTransceiver::do_start () send_command ("get context", false, false); } + QString HRD_info_path {data_path_.absoluteFilePath ("HRD Interface Information.txt")}; + QFile HRD_info_file {HRD_info_path}; + if (!HRD_info_file.open (QFile::WriteOnly | QFile::Text | QFile::Truncate)) + { + throw error {tr ("Failed to open file \"%1\".").arg (HRD_info_path)}; + } + QTextStream HRD_info {&HRD_info_file}; + + auto id = send_command ("get id", false, false); + auto version = send_command ("get version", false, false); + #if WSJT_TRACE_CAT - qDebug () << send_command ("get id", false, false); - qDebug () << send_command ("get version", false, false); + qDebug () << "Id:" << id; + qDebug () << "Version:" << version; #endif + 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 ()) { @@ -165,8 +184,10 @@ void HRDTransceiver::do_start () throw error {tr ("Ham Radio Deluxe: no rig found")}; } + HRD_info << "Radios:\n"; Q_FOREACH (auto const& radio, radios) { + HRD_info << "\t" << radio << "\n"; auto entries = radio.trimmed ().split (':', QString::SkipEmptyParts); radios_.push_back (std::forward_as_tuple (entries[0].toUInt (), entries[1])); } @@ -179,7 +200,9 @@ void HRDTransceiver::do_start () } #endif - if (send_command ("get radio", false, false, true).isEmpty ()) + auto current_radio_name = send_command ("get radio", false, false, true); + HRD_info << "Current radio: " << current_radio_name << "\n"; + if (current_radio_name.isEmpty ()) { #if WSJT_TRACE_CAT qDebug () << "HRDTransceiver::do_start no rig found"; @@ -189,23 +212,37 @@ void HRDTransceiver::do_start () } 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 buttons_ = send_command ("get buttons").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~"); - #if WSJT_TRACE_CAT qDebug () << "HRD Buttons: " << buttons_; #endif + HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n"; dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', QString::SkipEmptyParts); - Q_FOREACH (auto d, dropdown_names_) + HRD_info << "Dropdowns:\n"; + Q_FOREACH (auto const& dd, dropdown_names_) { - dropdowns_[d] = send_command ("get dropdown-list {" + d + "}").trimmed ().split (',', QString::SkipEmptyParts); + auto selections = send_command ("get dropdown-list {" + dd + "}").trimmed ().split (',', QString::SkipEmptyParts); + HRD_info << "\t" << dd << ": {" << selections.join (", ") << "}\n"; + dropdowns_[dd] = selections; } +#if WSJT_TRACE_CAT + qDebug () << "HRD Dropdowns: " << dropdowns_; +#endif + sliders_ = send_command ("get sliders").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~"); + HRD_info << "Sliders:\n"; + HRD_info << "Sliders: {" << sliders_.join (", ") << "}\n"; + Q_FOREACH (auto const& s, sliders_) + { + auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', QString::SkipEmptyParts); + HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n"; + } #if WSJT_TRACE_CAT qDebug () << "HRD Dropdowns: " << dropdowns_; #endif diff --git a/HRDTransceiver.hpp b/HRDTransceiver.hpp index f0001b7d3..4afa540ee 100644 --- a/HRDTransceiver.hpp +++ b/HRDTransceiver.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "TransceiverFactory.hpp" #include "PollingTransceiver.hpp" @@ -30,7 +31,11 @@ public: static void register_transceivers (TransceiverFactory::Transceivers *, int id); // takes ownership of wrapped Transceiver - explicit HRDTransceiver (std::unique_ptr wrapped, QString const& server, bool use_for_ptt, int poll_interval); + explicit HRDTransceiver (std::unique_ptr wrapped + , QString const& server + , bool use_for_ptt + , int poll_interval + , QDir const& data_path); ~HRDTransceiver (); protected: @@ -77,6 +82,8 @@ private: QString server_; // The TCP/IP addrress and port for // the HRD server. + QDir data_path_; // Directory to write files to + QTcpSocket * hrd_; // The TCP/IP client that links to the // HRD server. @@ -100,6 +107,8 @@ private: // drop down selections // available. + QStringList sliders_; // The sliders available. + int vfo_A_button_; // The button we use to select VFO // A. May be -1 if none available. diff --git a/TransceiverFactory.cpp b/TransceiverFactory.cpp index bb6c04145..c986802b9 100644 --- a/TransceiverFactory.cpp +++ b/TransceiverFactory.cpp @@ -95,172 +95,174 @@ bool TransceiverFactory::has_asynchronous_CAT (QString const& name) const } std::unique_ptr TransceiverFactory::create (QString const& name - , QString const& cat_port - , int cat_baud - , DataBits cat_data_bits - , StopBits cat_stop_bits - , Handshake cat_handshake - , bool cat_dtr_always_on - , bool cat_rts_always_on - , PTTMethod ptt_type - , TXAudioSource ptt_use_data_ptt - , SplitMode split_mode - , QString const& ptt_port - , int poll_interval - , QThread * target_thread) + , QString const& cat_port + , int cat_baud + , DataBits cat_data_bits + , StopBits cat_stop_bits + , Handshake cat_handshake + , bool cat_dtr_always_on + , bool cat_rts_always_on + , PTTMethod ptt_type + , TXAudioSource ptt_use_data_ptt + , SplitMode split_mode + , QString const& ptt_port + , int poll_interval + , QDir const& data_path + , QThread * target_thread + ) { std::unique_ptr result; switch (supported_transceivers ()[name].model_number_) { case CommanderId: { - // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_always_on - , cat_rts_always_on - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; - if (target_thread) - { - basic_transceiver.get ()->moveToThread (target_thread); - } + // we start with a dummy HamlibTransceiver object instance that can support direct PTT + std::unique_ptr basic_transceiver { + new HamlibTransceiver { + supported_transceivers ()[basic_transceiver_name_].model_number_ + , cat_port + , cat_baud + , cat_data_bits + , cat_stop_bits + , cat_handshake + , cat_dtr_always_on + , cat_rts_always_on + , ptt_type + , ptt_use_data_ptt + , "CAT" == ptt_port ? "" : 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}); - if (target_thread) - { - result.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}); + if (target_thread) + { + result.get ()->moveToThread (target_thread); + } } break; case HRDId: { - // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_always_on - , cat_rts_always_on - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; - if (target_thread) - { - basic_transceiver.get ()->moveToThread (target_thread); - } + // we start with a dummy HamlibTransceiver object instance that can support direct PTT + std::unique_ptr basic_transceiver { + new HamlibTransceiver { + supported_transceivers ()[basic_transceiver_name_].model_number_ + , cat_port + , cat_baud + , cat_data_bits + , cat_stop_bits + , cat_handshake + , cat_dtr_always_on + , cat_rts_always_on + , ptt_type + , ptt_use_data_ptt + , "CAT" == ptt_port ? "" : 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}); - if (target_thread) - { - result.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, data_path}); + if (target_thread) + { + result.get ()->moveToThread (target_thread); + } } break; #if defined (WIN32) case OmniRigOneId: { - // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_always_on - , cat_rts_always_on - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; - if (target_thread) - { - basic_transceiver.get ()->moveToThread (target_thread); - } + // we start with a dummy HamlibTransceiver object instance that can support direct PTT + std::unique_ptr basic_transceiver { + new HamlibTransceiver { + supported_transceivers ()[basic_transceiver_name_].model_number_ + , cat_port + , cat_baud + , cat_data_bits + , cat_stop_bits + , cat_handshake + , cat_dtr_always_on + , cat_rts_always_on + , ptt_type + , ptt_use_data_ptt + , "CAT" == ptt_port ? "" : 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}); - if (target_thread) - { - result.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}); + if (target_thread) + { + result.get ()->moveToThread (target_thread); + } } break; case OmniRigTwoId: { - // we start with a dummy HamlibTransceiver object instance that can support direct PTT - std::unique_ptr basic_transceiver { - new HamlibTransceiver { - supported_transceivers ()[basic_transceiver_name_].model_number_ - , cat_port - , cat_baud - , cat_data_bits - , cat_stop_bits - , cat_handshake - , cat_dtr_always_on - , cat_rts_always_on - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? "" : ptt_port - } - }; - if (target_thread) - { - basic_transceiver.get ()->moveToThread (target_thread); - } + // we start with a dummy HamlibTransceiver object instance that can support direct PTT + std::unique_ptr basic_transceiver { + new HamlibTransceiver { + supported_transceivers ()[basic_transceiver_name_].model_number_ + , cat_port + , cat_baud + , cat_data_bits + , cat_stop_bits + , cat_handshake + , cat_dtr_always_on + , cat_rts_always_on + , ptt_type + , ptt_use_data_ptt + , "CAT" == ptt_port ? "" : 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}); - if (target_thread) - { - result.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}); + if (target_thread) + { + result.get ()->moveToThread (target_thread); + } } break; #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_always_on - , cat_rts_always_on - , ptt_type - , ptt_use_data_ptt - , "CAT" == ptt_port ? cat_port : ptt_port - , poll_interval - }); - if (target_thread) - { - result.get ()->moveToThread (target_thread); - } + supported_transceivers ()[name].model_number_ + , cat_port + , cat_baud + , cat_data_bits + , cat_stop_bits + , cat_handshake + , cat_dtr_always_on + , cat_rts_always_on + , ptt_type + , ptt_use_data_ptt + , "CAT" == ptt_port ? cat_port : ptt_port + , poll_interval + }); + if (target_thread) + { + result.get ()->moveToThread (target_thread); + } break; } @@ -269,9 +271,9 @@ std::unique_ptr TransceiverFactory::create (QString const& name // wrap the Transceiver object instance with a decorator that emulates split mode result.reset (new EmulateSplitTransceiver {std::move (result)}); if (target_thread) - { - result.get ()->moveToThread (target_thread); - } + { + result.get ()->moveToThread (target_thread); + } } return std::move (result); diff --git a/TransceiverFactory.hpp b/TransceiverFactory.hpp index 176c91612..44f06ea33 100644 --- a/TransceiverFactory.hpp +++ b/TransceiverFactory.hpp @@ -12,6 +12,7 @@ class QString; class QThread; +class QDir; // // Transceiver Factory @@ -36,11 +37,11 @@ public: enum PortType {none, serial, network}; explicit Capabilities (int model_number = 0 - , PortType port_type = none - , bool has_CAT_PTT = false - , bool has_CAT_PTT_mic_data = false - , bool has_CAT_indirect_serial_PTT = false - , bool asynchronous = false) + , PortType port_type = none + , bool has_CAT_PTT = false + , bool has_CAT_PTT_mic_data = false + , bool has_CAT_indirect_serial_PTT = false + , bool asynchronous = false) : model_number_ {model_number} , port_type_ {port_type} , has_CAT_PTT_ {has_CAT_PTT} @@ -99,23 +100,24 @@ public: // type // std::unique_ptr create (QString const& name // from supported_transceivers () key - , QString const& cat_port // serial port device name or empty - , int cat_baud - , DataBits cat_data_bits - , StopBits cat_stop_bits - , Handshake cat_handshake - , bool cat_dtr_always_on // to power interface - , bool cat_rts_always_on // 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 - ); - + , QString const& cat_port // serial port device name or empty + , int cat_baud + , DataBits cat_data_bits + , StopBits cat_stop_bits + , Handshake cat_handshake + , bool cat_dtr_always_on // to power interface + , bool cat_rts_always_on // 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 + , QDir const& data_path + , QThread * target_thread = nullptr + ); + private: - Transceivers transceivers_; + Transceivers transceivers_; }; //