Mute first reflector TX after TG activation

By default mute the first transmission after selecting a talk group.
This is good for reducing unneccessary talk group activations and to
allow local node DTMF command submission without disturbing an ongoing
QSO on a talk group.
This commit is contained in:
Tobias Blomberg 2019-10-20 19:04:21 +02:00
parent a2fa7c6f4b
commit dbfd1a8266
5 changed files with 46 additions and 5 deletions

View File

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

View File

@ -47,6 +47,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include <AsyncTcpClient.h>
#include <AsyncUdpSocket.h>
#include <AsyncAudioPassthrough.h>
#include <AsyncAudioValve.h>
#include <version/SVXLINK.h>
@ -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 */

View File

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

View File

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

View File

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