diff --git a/src/doc/man/svxlink.conf.5 b/src/doc/man/svxlink.conf.5 index ad3117ea..48b20d29 100644 --- a/src/doc/man/svxlink.conf.5 +++ b/src/doc/man/svxlink.conf.5 @@ -648,6 +648,17 @@ It is also possible to set audio codec parameters using the same configuration variables as documented for networked receivers and transmitters. For example, to lighten the encoder CPU load for the Opus encoder, set OPUS_ENC_COMPLEXITY to something lower than 9. +.TP +.B MUTE_FIRST_TX +Mute the first transmission after selecting a talk group. This feature is good +to have enabled for a number of reasons. One reason is to suppress short +openings of a talk group when someone just make a single transmission to test +the local node. Another reason is for to allow someone to submit DTMF commands +to the node without disturbing the reflector network. For example, if the local +node have opened up due to activity on a monitored talk group but a local user +wish to switch to another talk group, that local user can do that without +transmitting into the currently active talk group. This feature is enabled by +default. . .SS QSO Recorder Section . diff --git a/src/svxlink/svxlink/ReflectorLogic.cpp b/src/svxlink/svxlink/ReflectorLogic.cpp index dbc563d7..89a2f9b1 100644 --- a/src/svxlink/svxlink/ReflectorLogic.cpp +++ b/src/svxlink/svxlink/ReflectorLogic.cpp @@ -47,6 +47,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include +#include #include @@ -133,7 +134,7 @@ ReflectorLogic::ReflectorLogic(Async::Config& cfg, const std::string& name) m_tg_select_timeout_cnt(0), m_selected_tg(0), m_previous_tg(0), m_event_handler(0), m_report_tg_timer(500, Async::Timer::TYPE_ONESHOT, false), - m_tg_local_activity(false), m_last_qsy(0) + m_tg_local_activity(false), m_last_qsy(0), m_logic_con_in_valve(0) { m_reconnect_timer.expired.connect( sigc::hide(mem_fun(*this, &ReflectorLogic::reconnect))); @@ -249,10 +250,24 @@ bool ReflectorLogic::initialize(void) m_logic_con_in = new Async::AudioStreamStateDetector; m_logic_con_in->sigStreamStateChanged.connect( sigc::mem_fun(*this, &ReflectorLogic::onLogicConInStreamStateChanged)); + AudioSource *prev_src = m_logic_con_in; + + bool mute_first_tx = true; + cfg().getValue(name(), "MUTE_FIRST_TX", mute_first_tx); + if (mute_first_tx) + { + m_logic_con_in_valve = new Async::AudioValve; + m_logic_con_in_valve->setOpen(false); + prev_src->registerSink(m_logic_con_in_valve); + prev_src = m_logic_con_in_valve; + } + + m_enc_endpoint = prev_src; + prev_src = 0; // Create dummy audio codec used before setting the real encoder if (!setAudioCodec("DUMMY")) { return false; } - AudioSource *prev_src = m_dec; + prev_src = m_dec; // Create jitter buffer AudioFifo *fifo = new Async::AudioFifo(2*INTERNAL_SAMPLE_RATE); @@ -1352,7 +1367,7 @@ bool ReflectorLogic::setAudioCodec(const std::string& codec_name) mem_fun(*this, &ReflectorLogic::sendEncodedAudio)); m_enc->flushEncodedSamples.connect( mem_fun(*this, &ReflectorLogic::flushEncodedAudio)); - m_logic_con_in->registerSink(m_enc, false); + m_enc_endpoint->registerSink(m_enc, false); string opt_prefix(m_enc->name()); opt_prefix += "_ENC_"; @@ -1423,7 +1438,14 @@ void ReflectorLogic::onLogicConInStreamStateChanged(bool is_active, { //cout << "### ReflectorLogic::onLogicConInStreamStateChanged: is_active=" // << is_active << " is_idle=" << is_idle << endl; - if (!is_idle) + if (is_idle) + { + if ((m_logic_con_in_valve != 0) && (m_selected_tg > 0)) + { + m_logic_con_in_valve->setOpen(true); + } + } + else { if (m_tg_select_timeout_cnt == 0) // No TG currently selected { @@ -1497,6 +1519,10 @@ void ReflectorLogic::selectTg(uint32_t tg, const std::string& event) m_tg_local_activity = false; m_event_handler->setVariable(name() + "::selected_tg", m_selected_tg); m_event_handler->setVariable(name() + "::previous_tg", m_previous_tg); + if ((m_logic_con_in_valve != 0 ) && (tg == 0)) + { + m_logic_con_in_valve->setOpen(false); + } } m_tg_select_timeout_cnt = (tg > 0) ? m_tg_select_timeout : 0; } /* ReflectorLogic::selectTg */ diff --git a/src/svxlink/svxlink/ReflectorLogic.h b/src/svxlink/svxlink/ReflectorLogic.h index 26ab52f8..6f95be12 100644 --- a/src/svxlink/svxlink/ReflectorLogic.h +++ b/src/svxlink/svxlink/ReflectorLogic.h @@ -72,6 +72,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA namespace Async { class UdpSocket; + class AudioValve; }; class ReflectorMsg; @@ -244,6 +245,8 @@ class ReflectorLogic : public LogicBase uint32_t m_last_qsy; MonitorTgsSet m_monitor_tgs; Json::Value m_node_info; + Async::AudioSource* m_enc_endpoint; + Async::AudioValve* m_logic_con_in_valve; ReflectorLogic(const ReflectorLogic&); ReflectorLogic& operator=(const ReflectorLogic&); diff --git a/src/svxlink/svxlink/svxlink.conf.in b/src/svxlink/svxlink/svxlink.conf.in index 2b1c23e4..48ce7042 100644 --- a/src/svxlink/svxlink/svxlink.conf.in +++ b/src/svxlink/svxlink/svxlink.conf.in @@ -95,6 +95,7 @@ AUTH_KEY="Change this key now!" ANNOUNCE_REMOTE_MIN_INTERVAL=300 EVENT_HANDLER=@SVX_SHARE_INSTALL_DIR@/events.tcl #NODE_INFO_FILE=@SVX_SYSCONF_INSTALL_DIR@/node_info.json +#MUTE_FIRST_TX=1 [LinkToR4] CONNECT_LOGICS=RepeaterLogic:94:SK3AB,SimplexLogic:92:SK3CD diff --git a/src/versions b/src/versions index aa8f2c36..7e854f25 100644 --- a/src/versions +++ b/src/versions @@ -11,7 +11,7 @@ LIBECHOLIB=1.3.3 LIBASYNC=1.6.0.99.3-reflector_tg # SvxLink versions -SVXLINK=1.7.99.11-reflector_tg +SVXLINK=1.7.99.12-reflector_tg MODULE_HELP=1.0.0 MODULE_PARROT=1.1.1 MODULE_ECHO_LINK=1.5.0