mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 01:55:48 -05:00
PTT: vox (1)
This commit is contained in:
parent
7de805b433
commit
79ac722e79
@ -1220,6 +1220,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
|
||||
|
||||
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
||||
{
|
||||
(void) dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1214,6 +1214,7 @@ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index
|
||||
|
||||
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
||||
{
|
||||
(void) dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,13 @@ bool SimplePTT::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
void SimplePTT::getAudioPeak(float& peak)
|
||||
{
|
||||
if (m_worker) {
|
||||
m_worker->getAudioPeak(peak);
|
||||
}
|
||||
}
|
||||
|
||||
void SimplePTT::applySettings(const SimplePTTSettings& settings, bool force)
|
||||
{
|
||||
qDebug() << "SimplePTT::applySettings:"
|
||||
@ -156,6 +163,11 @@ void SimplePTT::applySettings(const SimplePTTSettings& settings, bool force)
|
||||
<< " m_txDeviceSetIndex: " << settings.m_txDeviceSetIndex
|
||||
<< " m_rx2TxDelayMs: " << settings.m_rx2TxDelayMs
|
||||
<< " m_tx2RxDelayMs: " << settings.m_tx2RxDelayMs
|
||||
<< " m_vox: " << settings.m_vox
|
||||
<< " m_voxEnable: " << settings.m_voxEnable
|
||||
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||
<< " m_voxLevel: " << settings.m_voxLevel
|
||||
<< " m_voxHold: " << settings.m_voxHold
|
||||
<< " force: " << force;
|
||||
|
||||
QList<QString> reverseAPIKeys;
|
||||
@ -178,6 +190,18 @@ void SimplePTT::applySettings(const SimplePTTSettings& settings, bool force)
|
||||
if ((m_settings.m_tx2RxDelayMs != settings.m_tx2RxDelayMs) || force) {
|
||||
reverseAPIKeys.append("tx2RxDelayMs");
|
||||
}
|
||||
if ((m_settings.m_vox != settings.m_vox) || force) {
|
||||
reverseAPIKeys.append("vox");
|
||||
}
|
||||
if ((m_settings.m_voxEnable != settings.m_voxEnable) || force) {
|
||||
reverseAPIKeys.append("voxEnable");
|
||||
}
|
||||
if ((m_settings.m_voxHold != settings.m_voxHold) || force) {
|
||||
reverseAPIKeys.append("voxHold");
|
||||
}
|
||||
if ((m_settings.m_voxLevel != settings.m_voxLevel) || force) {
|
||||
reverseAPIKeys.append("voxLevel");
|
||||
}
|
||||
|
||||
SimplePTTWorker::MsgConfigureSimplePTTWorker *msg = SimplePTTWorker::MsgConfigureSimplePTTWorker::create(
|
||||
settings, force
|
||||
@ -321,6 +345,10 @@ void SimplePTT::webapiFormatFeatureSettings(
|
||||
response.getSimplePttSettings()->setTxDeviceSetIndex(settings.m_txDeviceSetIndex);
|
||||
response.getSimplePttSettings()->setRx2TxDelayMs(settings.m_rx2TxDelayMs);
|
||||
response.getSimplePttSettings()->setTx2RxDelayMs(settings.m_tx2RxDelayMs);
|
||||
response.getSimplePttSettings()->setVox(settings.m_vox ? 1 : 0);
|
||||
response.getSimplePttSettings()->setVoxEnable(settings.m_voxEnable ? 1 : 0);
|
||||
response.getSimplePttSettings()->setVoxHold(settings.m_voxHold);
|
||||
response.getSimplePttSettings()->setVoxLevel(settings.m_voxLevel);
|
||||
|
||||
response.getSimplePttSettings()->setUseReverseApi(settings.m_useReverseAPI ? 1 : 0);
|
||||
|
||||
@ -358,6 +386,18 @@ void SimplePTT::webapiUpdateFeatureSettings(
|
||||
if (featureSettingsKeys.contains("tx2RxDelayMs")) {
|
||||
settings.m_tx2RxDelayMs = response.getSimplePttSettings()->getTx2RxDelayMs();
|
||||
}
|
||||
if (featureSettingsKeys.contains("vox")) {
|
||||
settings.m_vox = response.getSimplePttSettings()->getVox() != 0;
|
||||
}
|
||||
if (featureSettingsKeys.contains("voxEnable")) {
|
||||
settings.m_voxEnable = response.getSimplePttSettings()->getVoxEnable() != 0;
|
||||
}
|
||||
if (featureSettingsKeys.contains("voxHold")) {
|
||||
settings.m_voxHold = response.getSimplePttSettings()->getVoxHold();
|
||||
}
|
||||
if (featureSettingsKeys.contains("voxLevel")) {
|
||||
settings.m_voxLevel = response.getSimplePttSettings()->getVoxLevel();
|
||||
}
|
||||
if (featureSettingsKeys.contains("useReverseAPI")) {
|
||||
settings.m_useReverseAPI = response.getSimplePttSettings()->getUseReverseApi() != 0;
|
||||
}
|
||||
@ -410,6 +450,18 @@ void SimplePTT::webapiReverseSendSettings(QList<QString>& channelSettingsKeys, c
|
||||
if (channelSettingsKeys.contains("tx2RxDelayMs") || force) {
|
||||
swgSimplePTTSettings->setTx2RxDelayMs(settings.m_tx2RxDelayMs);
|
||||
}
|
||||
if (channelSettingsKeys.contains("vox") || force) {
|
||||
swgSimplePTTSettings->setVox(settings.m_vox ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("voxEnable") || force) {
|
||||
swgSimplePTTSettings->setVoxEnable(settings.m_voxEnable ? 1 : 0);
|
||||
}
|
||||
if (channelSettingsKeys.contains("voxHold") || force) {
|
||||
swgSimplePTTSettings->setVoxHold(settings.m_voxHold);
|
||||
}
|
||||
if (channelSettingsKeys.contains("voxLevel") || force) {
|
||||
swgSimplePTTSettings->setVoxLevel(settings.m_voxLevel);
|
||||
}
|
||||
|
||||
QString channelSettingsURL = QString("http://%1:%2/sdrangel/featureset/%3/feature/%4/settings")
|
||||
.arg(settings.m_reverseAPIAddress)
|
||||
|
@ -142,6 +142,8 @@ public:
|
||||
const QStringList& featureSettingsKeys,
|
||||
SWGSDRangel::SWGFeatureSettings& response);
|
||||
|
||||
void getAudioPeak(float& peak);
|
||||
|
||||
static const char* const m_featureIdURI;
|
||||
static const char* const m_featureId;
|
||||
|
||||
|
@ -19,7 +19,11 @@
|
||||
|
||||
#include "feature/featureuiset.h"
|
||||
#include "gui/basicfeaturesettingsdialog.h"
|
||||
#include "gui/crightclickenabler.h"
|
||||
#include "gui/audioselectdialog.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "device/deviceset.h"
|
||||
#include "util/db.h"
|
||||
#include "maincore.h"
|
||||
|
||||
#include "ui_simplepttgui.h"
|
||||
@ -89,6 +93,19 @@ bool SimplePTTGUI::handleMessage(const Message& message)
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (SimplePTTReport::MsgVox::match(message))
|
||||
{
|
||||
qDebug("SimplePTTGUI::handleMessage: SimplePTTReport::MsgVox");
|
||||
const SimplePTTReport::MsgVox& cfg = (const SimplePTTReport::MsgVox&) message;
|
||||
|
||||
if (cfg.getVox()) {
|
||||
ui->voxLevelText->setStyleSheet("QLabel { background-color : green; }");
|
||||
} else {
|
||||
ui->voxLevelText->setStyleSheet("QLabel { background:rgb(79,79,79); }");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (SimplePTT::MsgPTT::match(message))
|
||||
{
|
||||
qDebug("SimplePTTGUI::handleMessage: SimplePTT::MsgPTT");
|
||||
@ -145,9 +162,11 @@ SimplePTTGUI::SimplePTTGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Fea
|
||||
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(onMenuDialogCalled(const QPoint &)));
|
||||
connect(getInputMessageQueue(), SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||
CRightClickEnabler *voxRightClickEnabler = new CRightClickEnabler(ui->vox);
|
||||
connect(voxRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect()));
|
||||
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(1000);
|
||||
m_statusTimer.start(500);
|
||||
|
||||
m_statusTooltips.push_back("Idle"); // 0 - all off
|
||||
m_statusTooltips.push_back("Rx on"); // 1 - Rx on
|
||||
@ -180,6 +199,11 @@ void SimplePTTGUI::displaySettings()
|
||||
ui->rxtxDelay->setValue(m_settings.m_rx2TxDelayMs);
|
||||
ui->txrxDelay->setValue(m_settings.m_tx2RxDelayMs);
|
||||
restoreState(m_settings.m_rollupState);
|
||||
ui->vox->setChecked(m_settings.m_vox);
|
||||
ui->voxEnable->setChecked(m_settings.m_voxEnable);
|
||||
ui->voxLevel->setValue(m_settings.m_voxLevel);
|
||||
ui->voxLevelText->setText(tr("%1").arg(m_settings.m_voxLevel));
|
||||
ui->voxHold->setValue(m_settings.m_voxHold);
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
@ -354,6 +378,31 @@ void SimplePTTGUI::on_ptt_toggled(bool checked)
|
||||
applyPTT(checked);
|
||||
}
|
||||
|
||||
void SimplePTTGUI::on_vox_toggled(bool checked)
|
||||
{
|
||||
m_settings.m_vox = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SimplePTTGUI::on_voxEnable_clicked(bool checked)
|
||||
{
|
||||
m_settings.m_voxEnable = checked;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SimplePTTGUI::on_voxLevel_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_voxLevel = value;
|
||||
ui->voxLevelText->setText(tr("%1dB").arg(m_settings.m_voxLevel));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SimplePTTGUI::on_voxHold_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_voxHold = value;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void SimplePTTGUI::updateStatus()
|
||||
{
|
||||
int state = m_simplePTT->getState();
|
||||
@ -381,6 +430,14 @@ void SimplePTTGUI::updateStatus()
|
||||
|
||||
m_lastFeatureState = state;
|
||||
}
|
||||
|
||||
if (m_settings.m_vox)
|
||||
{
|
||||
float peak;
|
||||
m_simplePTT->getAudioPeak(peak);
|
||||
int peakDB = CalcDb::dbPower(peak);
|
||||
ui->audioPeak->setText(tr("%1 dB").arg(peakDB));
|
||||
}
|
||||
}
|
||||
|
||||
void SimplePTTGUI::applySettings(bool force)
|
||||
@ -400,3 +457,16 @@ void SimplePTTGUI::applyPTT(bool tx)
|
||||
m_simplePTT->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
||||
void SimplePTTGUI::audioSelect()
|
||||
{
|
||||
qDebug("SimplePTTGUI::audioSelect");
|
||||
AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName);
|
||||
audioSelect.exec();
|
||||
|
||||
if (audioSelect.m_selected)
|
||||
{
|
||||
m_settings.m_audioDeviceName = audioSelect.m_audioDeviceName;
|
||||
applySettings();
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,12 @@ private slots:
|
||||
void on_rxtxDelay_valueChanged(int value);
|
||||
void on_txrxDelay_valueChanged(int value);
|
||||
void on_ptt_toggled(bool checked);
|
||||
void on_vox_toggled(bool checked);
|
||||
void on_voxEnable_clicked(bool checked);
|
||||
void on_voxLevel_valueChanged(int value);
|
||||
void on_voxHold_valueChanged(int value);
|
||||
void updateStatus();
|
||||
void audioSelect();
|
||||
};
|
||||
|
||||
|
||||
|
@ -92,6 +92,7 @@
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Liberation Sans</family>
|
||||
<pointsize>20</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
@ -132,6 +133,148 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="voxLayout">
|
||||
<item>
|
||||
<widget class="ButtonSwitch" name="vox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Toggle vox system - right click to select audio device</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../sdrgui/resources/res.qrc">
|
||||
<normaloff>:/audio_mic.png</normaloff>:/audio_mic.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="voxEnable">
|
||||
<property name="toolTip">
|
||||
<string>Enable vox to control PTT</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDial" name="voxLevel">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Vox threshold (dB)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-99</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>-20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="voxLevelText">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-20</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="audioPeak">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Audio signal peak in dB (with Vox on)</string>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>14</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-100 dB</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="voxHold">
|
||||
<property name="toolTip">
|
||||
<string>Vox delay (ms)</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="voxHoldUnits">
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="localDeviceLayout">
|
||||
<item>
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "simplepttreport.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(SimplePTTReport::MsgRadioState, Message)
|
||||
MESSAGE_CLASS_DEFINITION(SimplePTTReport::MsgVox, Message)
|
||||
|
||||
SimplePTTReport::SimplePTTReport()
|
||||
{}
|
||||
|
@ -34,8 +34,7 @@ public:
|
||||
public:
|
||||
RadioState getState() const { return m_state; }
|
||||
|
||||
static MsgRadioState* create(RadioState state)
|
||||
{
|
||||
static MsgRadioState* create(RadioState state) {
|
||||
return new MsgRadioState(state);
|
||||
}
|
||||
|
||||
@ -48,6 +47,25 @@ public:
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgVox : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
bool getVox() const { return m_vox; }
|
||||
|
||||
static MsgVox* create(bool vox) {
|
||||
return new MsgVox(vox);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_vox;
|
||||
|
||||
MsgVox(bool vox) :
|
||||
Message(),
|
||||
m_vox(vox)
|
||||
{}
|
||||
};
|
||||
|
||||
SimplePTTReport();
|
||||
~SimplePTTReport();
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "util/simpleserializer.h"
|
||||
#include "settings/serializable.h"
|
||||
#include "audio/audiodevicemanager.h"
|
||||
|
||||
#include "simplepttsettings.h"
|
||||
|
||||
@ -35,6 +36,11 @@ void SimplePTTSettings::resetToDefaults()
|
||||
m_txDeviceSetIndex = -1;
|
||||
m_rx2TxDelayMs = 100;
|
||||
m_tx2RxDelayMs = 100;
|
||||
m_audioDeviceName = AudioDeviceManager::m_defaultDeviceName;
|
||||
m_voxLevel = -20;
|
||||
m_voxHold = 500;
|
||||
m_vox = false;
|
||||
m_voxEnable = false;
|
||||
m_useReverseAPI = false;
|
||||
m_reverseAPIAddress = "127.0.0.1";
|
||||
m_reverseAPIPort = 8888;
|
||||
@ -58,6 +64,11 @@ QByteArray SimplePTTSettings::serialize() const
|
||||
s.writeU32(10, m_reverseAPIFeatureSetIndex);
|
||||
s.writeU32(11, m_reverseAPIFeatureIndex);
|
||||
s.writeBlob(12, m_rollupState);
|
||||
s.writeString(13, m_audioDeviceName);
|
||||
s.writeS32(14, m_voxLevel);
|
||||
s.writeBool(15, m_vox);
|
||||
s.writeBool(16, m_voxEnable);
|
||||
s.writeS32(17, m_voxHold);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -99,6 +110,11 @@ bool SimplePTTSettings::deserialize(const QByteArray& data)
|
||||
d.readU32(11, &utmp, 0);
|
||||
m_reverseAPIFeatureIndex = utmp > 99 ? 99 : utmp;
|
||||
d.readBlob(12, &m_rollupState);
|
||||
d.readString(13, &m_audioDeviceName, AudioDeviceManager::m_defaultDeviceName);
|
||||
d.readS32(14, &m_voxLevel, -20);
|
||||
d.readBool(15, &m_vox, false);
|
||||
d.readBool(16, &m_voxEnable, false);
|
||||
d.readS32(16, &m_voxHold, 500);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ struct SimplePTTSettings
|
||||
int m_txDeviceSetIndex;
|
||||
unsigned int m_rx2TxDelayMs;
|
||||
unsigned int m_tx2RxDelayMs;
|
||||
QString m_audioDeviceName; //!< for Vox
|
||||
int m_voxLevel; //!< Vox threshold level in dB
|
||||
int m_voxHold; //!< Vox hold in milliseconds
|
||||
bool m_vox;
|
||||
bool m_voxEnable;
|
||||
bool m_useReverseAPI;
|
||||
QString m_reverseAPIAddress;
|
||||
uint16_t m_reverseAPIPort;
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include "SWGErrorResponse.h"
|
||||
|
||||
#include "webapi/webapiadapterinterface.h"
|
||||
#include "audio/audiodevicemanager.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "util/db.h"
|
||||
|
||||
#include "simplepttreport.h"
|
||||
#include "simplepttworker.h"
|
||||
@ -34,9 +37,16 @@ SimplePTTWorker::SimplePTTWorker(WebAPIAdapterInterface *webAPIAdapterInterface)
|
||||
m_msgQueueToGUI(nullptr),
|
||||
m_running(false),
|
||||
m_tx(false),
|
||||
m_audioFifo(12000),
|
||||
m_audioSampleRate(48000),
|
||||
m_voxLevel(1.0),
|
||||
m_voxHoldCount(0),
|
||||
m_voxState(false),
|
||||
m_updateTimer(this),
|
||||
m_mutex(QMutex::Recursive)
|
||||
{
|
||||
m_audioReadBuffer.resize(16384);
|
||||
m_audioReadBufferFill = 0;
|
||||
qDebug("SimplePTTWorker::SimplePTTWorker");
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||
}
|
||||
@ -44,6 +54,8 @@ SimplePTTWorker::SimplePTTWorker(WebAPIAdapterInterface *webAPIAdapterInterface)
|
||||
SimplePTTWorker::~SimplePTTWorker()
|
||||
{
|
||||
m_inputMessageQueue.clear();
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
audioDeviceManager->removeAudioSource(&m_audioFifo);
|
||||
}
|
||||
|
||||
void SimplePTTWorker::reset()
|
||||
@ -115,7 +127,48 @@ void SimplePTTWorker::applySettings(const SimplePTTSettings& settings, bool forc
|
||||
<< " m_txDeviceSetIndex: " << settings.m_txDeviceSetIndex
|
||||
<< " m_rx2TxDelayMs: " << settings.m_rx2TxDelayMs
|
||||
<< " m_tx2RxDelayMs: " << settings.m_tx2RxDelayMs
|
||||
<< " m_vox: " << settings.m_vox
|
||||
<< " m_voxEnable: " << settings.m_voxEnable
|
||||
<< " m_audioDeviceName: " << settings.m_audioDeviceName
|
||||
<< " m_voxLevel: " << settings.m_voxLevel
|
||||
<< " m_voxHold: " << settings.m_voxHold
|
||||
<< " force: " << force;
|
||||
|
||||
if ((settings.m_audioDeviceName != m_settings.m_audioDeviceName) || force)
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
|
||||
int audioDeviceIndex = audioDeviceManager->getInputDeviceIndex(settings.m_audioDeviceName);
|
||||
audioDeviceManager->removeAudioSource(&m_audioFifo);
|
||||
audioDeviceManager->addAudioSource(&m_audioFifo, getInputMessageQueue(), audioDeviceIndex);
|
||||
m_audioSampleRate = audioDeviceManager->getInputSampleRate(audioDeviceIndex);
|
||||
}
|
||||
|
||||
if ((settings.m_vox != m_settings.m_vox) || force)
|
||||
{
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
m_voxHoldCount = 0;
|
||||
m_audioReadBufferFill = 0;
|
||||
m_voxState = false;
|
||||
|
||||
if (m_msgQueueToGUI)
|
||||
{
|
||||
SimplePTTReport::MsgVox *msg = SimplePTTReport::MsgVox::create(false);
|
||||
m_msgQueueToGUI->push(msg);
|
||||
}
|
||||
|
||||
if (settings.m_vox) {
|
||||
connect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
|
||||
} else {
|
||||
disconnect(&m_audioFifo, SIGNAL(dataReady()), this, SLOT(handleAudio()));
|
||||
}
|
||||
}
|
||||
|
||||
if ((settings.m_voxLevel != m_settings.m_voxLevel) || force)
|
||||
{
|
||||
m_voxLevel = CalcDb::powerFromdB(settings.m_voxLevel);
|
||||
}
|
||||
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
@ -126,29 +179,29 @@ void SimplePTTWorker::sendPTT(bool tx)
|
||||
bool switchedOff = false;
|
||||
m_mutex.lock();
|
||||
|
||||
if (tx)
|
||||
if (tx)
|
||||
{
|
||||
if (m_settings.m_rxDeviceSetIndex >= 0)
|
||||
if (m_settings.m_rxDeviceSetIndex >= 0)
|
||||
{
|
||||
m_tx = false;
|
||||
switchedOff = turnDevice(false);
|
||||
}
|
||||
|
||||
if (m_settings.m_txDeviceSetIndex >= 0)
|
||||
|
||||
if (m_settings.m_txDeviceSetIndex >= 0)
|
||||
{
|
||||
m_tx = true;
|
||||
m_updateTimer.start(m_settings.m_rx2TxDelayMs);
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_settings.m_txDeviceSetIndex >= 0)
|
||||
if (m_settings.m_txDeviceSetIndex >= 0)
|
||||
{
|
||||
m_tx = true;
|
||||
switchedOff = turnDevice(false);
|
||||
}
|
||||
|
||||
if (m_settings.m_rxDeviceSetIndex >= 0)
|
||||
if (m_settings.m_rxDeviceSetIndex >= 0)
|
||||
{
|
||||
m_tx = false;
|
||||
m_updateTimer.start(m_settings.m_tx2RxDelayMs);
|
||||
@ -190,7 +243,7 @@ bool SimplePTTWorker::turnDevice(bool on)
|
||||
SWGSDRangel::SWGDeviceState response;
|
||||
SWGSDRangel::SWGErrorResponse error;
|
||||
int httpCode;
|
||||
|
||||
|
||||
if (on) {
|
||||
httpCode = m_webAPIAdapterInterface->devicesetDeviceRunPost(
|
||||
m_tx ? m_settings.m_txDeviceSetIndex : m_settings.m_rxDeviceSetIndex, response, error);
|
||||
@ -208,4 +261,63 @@ bool SimplePTTWorker::turnDevice(bool on)
|
||||
qWarning("SimplePTTWorker::turnDevice: error: %s", qPrintable(*error.getMessage()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimplePTTWorker::handleAudio()
|
||||
{
|
||||
unsigned int nbRead;
|
||||
QMutexLocker mlock(&m_mutex);
|
||||
|
||||
while ((nbRead = m_audioFifo.read(reinterpret_cast<quint8*>(&m_audioReadBuffer[m_audioReadBufferFill]), 4096)) != 0)
|
||||
{
|
||||
if (m_audioReadBufferFill + nbRead + 4096 < m_audioReadBuffer.size())
|
||||
{
|
||||
m_audioReadBufferFill += nbRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool voxState = m_voxState;
|
||||
|
||||
for (const auto &it : m_audioReadBuffer)
|
||||
{
|
||||
std::complex<float> za{it.l / 32768.0f, it.r / 32768.0f};
|
||||
float magSq = std::norm(za);
|
||||
|
||||
if (magSq > m_audioMagsqPeak) {
|
||||
m_audioMagsqPeak = magSq;
|
||||
}
|
||||
|
||||
if (magSq > m_voxLevel)
|
||||
{
|
||||
voxState = true;
|
||||
m_voxHoldCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_voxHoldCount < (m_settings.m_voxHold * m_audioSampleRate) / 1000) {
|
||||
m_voxHoldCount++;
|
||||
} else {
|
||||
voxState = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (voxState != m_voxState)
|
||||
{
|
||||
if (m_settings.m_voxEnable) {
|
||||
sendPTT(voxState);
|
||||
}
|
||||
|
||||
if (m_msgQueueToGUI)
|
||||
{
|
||||
SimplePTTReport::MsgVox *msg = SimplePTTReport::MsgVox::create(voxState);
|
||||
m_msgQueueToGUI->push(msg);
|
||||
}
|
||||
|
||||
m_voxState = voxState;
|
||||
}
|
||||
}
|
||||
|
||||
m_audioReadBufferFill = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "util/message.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "audio/audiofifo.h"
|
||||
|
||||
#include "simplepttsettings.h"
|
||||
|
||||
@ -83,6 +84,12 @@ public:
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
void setMessageQueueToGUI(MessageQueue *messageQueue) { m_msgQueueToGUI = messageQueue; }
|
||||
|
||||
void getAudioPeak(float& peak)
|
||||
{
|
||||
peak = m_audioMagsqPeak;
|
||||
m_audioMagsqPeak = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
WebAPIAdapterInterface *m_webAPIAdapterInterface;
|
||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
||||
@ -90,6 +97,14 @@ private:
|
||||
SimplePTTSettings m_settings;
|
||||
bool m_running;
|
||||
bool m_tx;
|
||||
AudioFifo m_audioFifo;
|
||||
AudioVector m_audioReadBuffer;
|
||||
unsigned int m_audioReadBufferFill;
|
||||
int m_audioSampleRate;
|
||||
float m_audioMagsqPeak;
|
||||
float m_voxLevel;
|
||||
int m_voxHoldCount;
|
||||
bool m_voxState;
|
||||
QTimer m_updateTimer;
|
||||
QMutex m_mutex;
|
||||
|
||||
@ -101,6 +116,7 @@ private:
|
||||
private slots:
|
||||
void handleInputMessages();
|
||||
void updateHardware();
|
||||
void handleAudio();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_SIMPLEPTTWORKER_H_
|
||||
#endif // INCLUDE_FEATURE_SIMPLEPTTWORKER_H_
|
||||
|
@ -11231,6 +11231,25 @@ margin-bottom: 20px;
|
||||
"type" : "integer",
|
||||
"description" : "Delay in milliseconds from Tx off to Rx on"
|
||||
},
|
||||
"vox" : {
|
||||
"type" : "integer",
|
||||
"description" : "Activate vox system\n * 0 - not active\n * 1 - active\n"
|
||||
},
|
||||
"voxEnable" : {
|
||||
"type" : "integer",
|
||||
"description" : "Allow vox to control PTT\n * 0 - vox does not control PTT\n * 1 - vox controls PTT\n"
|
||||
},
|
||||
"voxLevel" : {
|
||||
"type" : "integer",
|
||||
"description" : "Vox threshold level in dB"
|
||||
},
|
||||
"voxHold" : {
|
||||
"type" : "integer",
|
||||
"description" : "Vox hold timeout in milliseconds"
|
||||
},
|
||||
"audioDeviceName" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"useReverseAPI" : {
|
||||
"type" : "integer",
|
||||
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
|
||||
@ -51634,7 +51653,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2021-12-27T21:57:14.290+01:00
|
||||
Generated 2021-12-29T17:23:49.058+01:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -17,6 +17,26 @@ SimplePTTSettings:
|
||||
tx2RxDelayMs:
|
||||
description: Delay in milliseconds from Tx off to Rx on
|
||||
type: integer
|
||||
vox:
|
||||
type: integer
|
||||
description: >
|
||||
Activate vox system
|
||||
* 0 - not active
|
||||
* 1 - active
|
||||
voxEnable:
|
||||
type: integer
|
||||
description: >
|
||||
Allow vox to control PTT
|
||||
* 0 - vox does not control PTT
|
||||
* 1 - vox controls PTT
|
||||
voxLevel:
|
||||
type: integer
|
||||
description: Vox threshold level in dB
|
||||
voxHold:
|
||||
type: integer
|
||||
description: Vox hold timeout in milliseconds
|
||||
audioDeviceName:
|
||||
type: string
|
||||
useReverseAPI:
|
||||
description: Synchronize with reverse API (1 for yes, 0 for no)
|
||||
type: integer
|
||||
|
BIN
sdrgui/resources/audio_mic.png
Normal file
BIN
sdrgui/resources/audio_mic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
@ -1,5 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>audio_mic.png</file>
|
||||
<file>info.png</file>
|
||||
<file>darklight.png</file>
|
||||
<file>lightdark.png</file>
|
||||
|
@ -17,6 +17,26 @@ SimplePTTSettings:
|
||||
tx2RxDelayMs:
|
||||
description: Delay in milliseconds from Tx off to Rx on
|
||||
type: integer
|
||||
vox:
|
||||
type: integer
|
||||
description: >
|
||||
Activate vox system
|
||||
* 0 - not active
|
||||
* 1 - active
|
||||
voxEnable:
|
||||
type: integer
|
||||
description: >
|
||||
Allow vox to control PTT
|
||||
* 0 - vox does not control PTT
|
||||
* 1 - vox controls PTT
|
||||
voxLevel:
|
||||
type: integer
|
||||
description: Vox threshold level in dB
|
||||
voxHold:
|
||||
type: integer
|
||||
description: Vox hold timeout in milliseconds
|
||||
audioDeviceName:
|
||||
type: string
|
||||
useReverseAPI:
|
||||
description: Synchronize with reverse API (1 for yes, 0 for no)
|
||||
type: integer
|
||||
|
@ -11231,6 +11231,25 @@ margin-bottom: 20px;
|
||||
"type" : "integer",
|
||||
"description" : "Delay in milliseconds from Tx off to Rx on"
|
||||
},
|
||||
"vox" : {
|
||||
"type" : "integer",
|
||||
"description" : "Activate vox system\n * 0 - not active\n * 1 - active\n"
|
||||
},
|
||||
"voxEnable" : {
|
||||
"type" : "integer",
|
||||
"description" : "Allow vox to control PTT\n * 0 - vox does not control PTT\n * 1 - vox controls PTT\n"
|
||||
},
|
||||
"voxLevel" : {
|
||||
"type" : "integer",
|
||||
"description" : "Vox threshold level in dB"
|
||||
},
|
||||
"voxHold" : {
|
||||
"type" : "integer",
|
||||
"description" : "Vox hold timeout in milliseconds"
|
||||
},
|
||||
"audioDeviceName" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"useReverseAPI" : {
|
||||
"type" : "integer",
|
||||
"description" : "Synchronize with reverse API (1 for yes, 0 for no)"
|
||||
@ -51634,7 +51653,7 @@ except ApiException as e:
|
||||
</div>
|
||||
<div id="generator">
|
||||
<div class="content">
|
||||
Generated 2021-12-27T21:57:14.290+01:00
|
||||
Generated 2021-12-29T17:23:49.058+01:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -40,6 +40,16 @@ SWGSimplePTTSettings::SWGSimplePTTSettings() {
|
||||
m_rx2_tx_delay_ms_isSet = false;
|
||||
tx2_rx_delay_ms = 0;
|
||||
m_tx2_rx_delay_ms_isSet = false;
|
||||
vox = 0;
|
||||
m_vox_isSet = false;
|
||||
vox_enable = 0;
|
||||
m_vox_enable_isSet = false;
|
||||
vox_level = 0;
|
||||
m_vox_level_isSet = false;
|
||||
vox_hold = 0;
|
||||
m_vox_hold_isSet = false;
|
||||
audio_device_name = nullptr;
|
||||
m_audio_device_name_isSet = false;
|
||||
use_reverse_api = 0;
|
||||
m_use_reverse_api_isSet = false;
|
||||
reverse_api_address = nullptr;
|
||||
@ -70,6 +80,16 @@ SWGSimplePTTSettings::init() {
|
||||
m_rx2_tx_delay_ms_isSet = false;
|
||||
tx2_rx_delay_ms = 0;
|
||||
m_tx2_rx_delay_ms_isSet = false;
|
||||
vox = 0;
|
||||
m_vox_isSet = false;
|
||||
vox_enable = 0;
|
||||
m_vox_enable_isSet = false;
|
||||
vox_level = 0;
|
||||
m_vox_level_isSet = false;
|
||||
vox_hold = 0;
|
||||
m_vox_hold_isSet = false;
|
||||
audio_device_name = new QString("");
|
||||
m_audio_device_name_isSet = false;
|
||||
use_reverse_api = 0;
|
||||
m_use_reverse_api_isSet = false;
|
||||
reverse_api_address = new QString("");
|
||||
@ -93,6 +113,13 @@ SWGSimplePTTSettings::cleanup() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(audio_device_name != nullptr) {
|
||||
delete audio_device_name;
|
||||
}
|
||||
|
||||
if(reverse_api_address != nullptr) {
|
||||
delete reverse_api_address;
|
||||
}
|
||||
@ -124,6 +151,16 @@ SWGSimplePTTSettings::fromJsonObject(QJsonObject &pJson) {
|
||||
|
||||
::SWGSDRangel::setValue(&tx2_rx_delay_ms, pJson["tx2RxDelayMs"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&vox, pJson["vox"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&vox_enable, pJson["voxEnable"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&vox_level, pJson["voxLevel"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&vox_hold, pJson["voxHold"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&audio_device_name, pJson["audioDeviceName"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&use_reverse_api, pJson["useReverseAPI"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&reverse_api_address, pJson["reverseAPIAddress"], "QString", "QString");
|
||||
@ -168,6 +205,21 @@ SWGSimplePTTSettings::asJsonObject() {
|
||||
if(m_tx2_rx_delay_ms_isSet){
|
||||
obj->insert("tx2RxDelayMs", QJsonValue(tx2_rx_delay_ms));
|
||||
}
|
||||
if(m_vox_isSet){
|
||||
obj->insert("vox", QJsonValue(vox));
|
||||
}
|
||||
if(m_vox_enable_isSet){
|
||||
obj->insert("voxEnable", QJsonValue(vox_enable));
|
||||
}
|
||||
if(m_vox_level_isSet){
|
||||
obj->insert("voxLevel", QJsonValue(vox_level));
|
||||
}
|
||||
if(m_vox_hold_isSet){
|
||||
obj->insert("voxHold", QJsonValue(vox_hold));
|
||||
}
|
||||
if(audio_device_name != nullptr && *audio_device_name != QString("")){
|
||||
toJsonValue(QString("audioDeviceName"), audio_device_name, obj, QString("QString"));
|
||||
}
|
||||
if(m_use_reverse_api_isSet){
|
||||
obj->insert("useReverseAPI", QJsonValue(use_reverse_api));
|
||||
}
|
||||
@ -247,6 +299,56 @@ SWGSimplePTTSettings::setTx2RxDelayMs(qint32 tx2_rx_delay_ms) {
|
||||
this->m_tx2_rx_delay_ms_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGSimplePTTSettings::getVox() {
|
||||
return vox;
|
||||
}
|
||||
void
|
||||
SWGSimplePTTSettings::setVox(qint32 vox) {
|
||||
this->vox = vox;
|
||||
this->m_vox_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGSimplePTTSettings::getVoxEnable() {
|
||||
return vox_enable;
|
||||
}
|
||||
void
|
||||
SWGSimplePTTSettings::setVoxEnable(qint32 vox_enable) {
|
||||
this->vox_enable = vox_enable;
|
||||
this->m_vox_enable_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGSimplePTTSettings::getVoxLevel() {
|
||||
return vox_level;
|
||||
}
|
||||
void
|
||||
SWGSimplePTTSettings::setVoxLevel(qint32 vox_level) {
|
||||
this->vox_level = vox_level;
|
||||
this->m_vox_level_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGSimplePTTSettings::getVoxHold() {
|
||||
return vox_hold;
|
||||
}
|
||||
void
|
||||
SWGSimplePTTSettings::setVoxHold(qint32 vox_hold) {
|
||||
this->vox_hold = vox_hold;
|
||||
this->m_vox_hold_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGSimplePTTSettings::getAudioDeviceName() {
|
||||
return audio_device_name;
|
||||
}
|
||||
void
|
||||
SWGSimplePTTSettings::setAudioDeviceName(QString* audio_device_name) {
|
||||
this->audio_device_name = audio_device_name;
|
||||
this->m_audio_device_name_isSet = true;
|
||||
}
|
||||
|
||||
qint32
|
||||
SWGSimplePTTSettings::getUseReverseApi() {
|
||||
return use_reverse_api;
|
||||
@ -320,6 +422,21 @@ SWGSimplePTTSettings::isSet(){
|
||||
if(m_tx2_rx_delay_ms_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_vox_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_vox_enable_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_vox_level_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_vox_hold_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(audio_device_name && *audio_device_name != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_use_reverse_api_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
@ -60,6 +60,21 @@ public:
|
||||
qint32 getTx2RxDelayMs();
|
||||
void setTx2RxDelayMs(qint32 tx2_rx_delay_ms);
|
||||
|
||||
qint32 getVox();
|
||||
void setVox(qint32 vox);
|
||||
|
||||
qint32 getVoxEnable();
|
||||
void setVoxEnable(qint32 vox_enable);
|
||||
|
||||
qint32 getVoxLevel();
|
||||
void setVoxLevel(qint32 vox_level);
|
||||
|
||||
qint32 getVoxHold();
|
||||
void setVoxHold(qint32 vox_hold);
|
||||
|
||||
QString* getAudioDeviceName();
|
||||
void setAudioDeviceName(QString* audio_device_name);
|
||||
|
||||
qint32 getUseReverseApi();
|
||||
void setUseReverseApi(qint32 use_reverse_api);
|
||||
|
||||
@ -97,6 +112,21 @@ private:
|
||||
qint32 tx2_rx_delay_ms;
|
||||
bool m_tx2_rx_delay_ms_isSet;
|
||||
|
||||
qint32 vox;
|
||||
bool m_vox_isSet;
|
||||
|
||||
qint32 vox_enable;
|
||||
bool m_vox_enable_isSet;
|
||||
|
||||
qint32 vox_level;
|
||||
bool m_vox_level_isSet;
|
||||
|
||||
qint32 vox_hold;
|
||||
bool m_vox_hold_isSet;
|
||||
|
||||
QString* audio_device_name;
|
||||
bool m_audio_device_name_isSet;
|
||||
|
||||
qint32 use_reverse_api;
|
||||
bool m_use_reverse_api_isSet;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user