Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Kern <pkern@google.com>2021-04-11 22:58:20 +0300
committerPhilipp Kern <pkern@google.com>2021-04-20 22:53:12 +0300
commit80461598a5dc0f1d1e86a82332d1ec3e21cbed76 (patch)
tree228ec1f0d0061c72233d78c3340f3c5c3502b8dd
parent25666f727e364ae6d5b70cbdac2eacfa4a6dbd01 (diff)
FEAT(client): Implement a mute cue
The mute cue is played when speech is detected while the local client is muted. This reminds the user that they are still muted, which is especially useful when the overlay/client indication is not available (e.g. in full-screen games). This currently reuses the existing "audio on" cue. Implements #4866
-rw-r--r--src/mumble/AudioConfigDialog.cpp26
-rw-r--r--src/mumble/AudioConfigDialog.h4
-rw-r--r--src/mumble/AudioInput.cpp29
-rw-r--r--src/mumble/AudioInput.h6
-rw-r--r--src/mumble/AudioInput.ui184
-rw-r--r--src/mumble/Settings.cpp9
-rw-r--r--src/mumble/Settings.h4
7 files changed, 175 insertions, 87 deletions
diff --git a/src/mumble/AudioConfigDialog.cpp b/src/mumble/AudioConfigDialog.cpp
index bed102293..794520ed8 100644
--- a/src/mumble/AudioConfigDialog.cpp
+++ b/src/mumble/AudioConfigDialog.cpp
@@ -113,6 +113,7 @@ AudioInputDialog::AudioInputDialog(Settings &st) : ConfigWidget(st) {
qcbDevice->view()->setTextElideMode(Qt::ElideRight);
on_qcbPushClick_clicked(Global::get().s.bTxAudioCue);
+ on_qcbMuteCue_clicked(Global::get().s.bTxMuteCue);
on_Tick_timeout();
on_qcbIdleAction_currentIndexChanged(Global::get().s.iaeIdleAction);
@@ -156,6 +157,7 @@ void AudioInputDialog::load(const Settings &r) {
qlePushClickPathOn->setText(r.qsTxAudioCueOn);
qlePushClickPathOff->setText(r.qsTxAudioCueOff);
+ qleMuteCuePath->setText(r.qsTxMuteCue);
loadComboBox(qcbTransmit, r.atTransmit);
loadSlider(qsTransmitHold, r.iVoiceHold);
@@ -172,6 +174,7 @@ void AudioInputDialog::load(const Settings &r) {
loadCheckBox(qcbPushWindow, r.bShowPTTButtonWindow);
loadCheckBox(qcbPushClick, r.bTxAudioCue);
+ loadCheckBox(qcbMuteCue, r.bTxMuteCue);
loadSlider(qsQuality, r.iQuality);
loadCheckBox(qcbAllowLowDelay, r.bAllowLowDelay);
if (r.iSpeexNoiseCancelStrength != 0) {
@@ -297,6 +300,9 @@ void AudioInputDialog::save() const {
s.qsTxAudioCueOn = qlePushClickPathOn->text();
s.qsTxAudioCueOff = qlePushClickPathOff->text();
+ s.bTxMuteCue = qcbMuteCue->isChecked();
+ s.qsTxMuteCue = qleMuteCuePath->text();
+
s.qsAudioInput = qcbSystem->currentText();
s.echoOption = static_cast< EchoCancelOptionID >(qcbEcho->currentData().toInt());
s.bExclusiveInput = qcbExclusive->isChecked();
@@ -442,6 +448,26 @@ void AudioInputDialog::on_qpbPushClickPreview_clicked() {
}
}
+void AudioInputDialog::on_qcbMuteCue_clicked(bool b) {
+ qleMuteCuePath->setEnabled(b);
+ qpbMuteCueBrowse->setEnabled(b);
+ qpbMuteCuePreview->setEnabled(b);
+}
+
+void AudioInputDialog::on_qpbMuteCueBrowse_clicked() {
+ QString defaultpath(qleMuteCuePath->text());
+ QString qsnew = AudioOutputSample::browseForSndfile(defaultpath);
+ if (!qsnew.isEmpty())
+ qleMuteCuePath->setText(qsnew);
+}
+
+
+void AudioInputDialog::on_qpbMuteCuePreview_clicked() {
+ AudioOutputPtr ao = Global::get().ao;
+ if (ao)
+ ao->playSample(qleMuteCuePath->text());
+}
+
void AudioInputDialog::continuePlayback() {
AudioOutputPtr ao = Global::get().ao;
if (ao) {
diff --git a/src/mumble/AudioConfigDialog.h b/src/mumble/AudioConfigDialog.h
index 570703ec6..603d0e5e9 100644
--- a/src/mumble/AudioConfigDialog.h
+++ b/src/mumble/AudioConfigDialog.h
@@ -44,6 +44,10 @@ public slots:
void on_qpbPushClickPreview_clicked();
void on_qpbPushClickReset_clicked();
+ void on_qcbMuteCue_clicked(bool);
+ void on_qpbMuteCueBrowse_clicked();
+ void on_qpbMuteCuePreview_clicked();
+
void on_qsTransmitHold_valueChanged(int v);
void on_qsFrames_valueChanged(int v);
void on_qsQuality_valueChanged(int v);
diff --git a/src/mumble/AudioInput.cpp b/src/mumble/AudioInput.cpp
index 0ac244a40..ce2e23e23 100644
--- a/src/mumble/AudioInput.cpp
+++ b/src/mumble/AudioInput.cpp
@@ -1079,10 +1079,12 @@ void AudioInput::encodeAudioFrame(AudioChunk chunk) {
// instance this could mean we're currently whispering
bIsSpeech = bIsSpeech || (Global::get().iPushToTalk > 0);
- ClientUser *p = ClientUser::get(Global::get().uiSession);
+ ClientUser *p = ClientUser::get(Global::get().uiSession);
+ bool bTalkingWhenMuted = false;
if (Global::get().s.bMute || ((Global::get().s.lmLoopMode != Settings::Local) && p && (p->bMute || p->bSuppress))
|| Global::get().bPushToMute || (voiceTargetID < 0)) {
- bIsSpeech = false;
+ bTalkingWhenMuted = bIsSpeech;
+ bIsSpeech = false;
}
if (bIsSpeech) {
@@ -1102,12 +1104,25 @@ void AudioInput::encodeAudioFrame(AudioChunk chunk) {
p->setTalking(Settings::Shouting);
}
- if (Global::get().s.bTxAudioCue && Global::get().uiSession != 0) {
+ if (Global::get().uiSession != 0 && (Global::get().s.bTxAudioCue || Global::get().s.bTxMuteCue)) {
AudioOutputPtr ao = Global::get().ao;
- if (bIsSpeech && !bPreviousVoice && ao)
- ao->playSample(Global::get().s.qsTxAudioCueOn);
- else if (ao && !bIsSpeech && bPreviousVoice)
- ao->playSample(Global::get().s.qsTxAudioCueOff);
+
+ if (ao) {
+ if (Global::get().s.bTxAudioCue) {
+ if (bIsSpeech && !bPreviousVoice) {
+ ao->playSample(Global::get().s.qsTxAudioCueOn);
+ } else if (!bIsSpeech && bPreviousVoice) {
+ ao->playSample(Global::get().s.qsTxAudioCueOff);
+ }
+ }
+
+ if (Global::get().s.bTxMuteCue && !Global::get().s.bDeaf && bTalkingWhenMuted) {
+ if (!qetLastMuteCue.isValid() || qetLastMuteCue.elapsed() > iMuteCueDelay) {
+ qetLastMuteCue.start();
+ ao->playSample(Global::get().s.qsTxMuteCue);
+ }
+ }
+ }
}
if (!bIsSpeech && !bPreviousVoice) {
diff --git a/src/mumble/AudioInput.h b/src/mumble/AudioInput.h
index d69c28f84..31804bbec 100644
--- a/src/mumble/AudioInput.h
+++ b/src/mumble/AudioInput.h
@@ -6,6 +6,7 @@
#ifndef MUMBLE_MUMBLE_AUDIOINPUT_H_
#define MUMBLE_MUMBLE_AUDIOINPUT_H_
+#include <QElapsedTimer>
#include <QtCore/QObject>
#include <QtCore/QThread>
#include <boost/array.hpp>
@@ -193,6 +194,8 @@ private:
int encodeOpusFrame(short *source, int size, EncodingOutputBuffer &buffer);
int encodeCELTFrame(short *pSource, EncodingOutputBuffer &buffer);
+ QElapsedTimer qetLastMuteCue;
+
protected:
MessageHandler::UDPMessageType umtType;
SampleFormat eMicFormat, eEchoFormat;
@@ -227,6 +230,9 @@ protected:
/// Number of 10ms audio "frames" per packet (!= frames in packet)
int iAudioFrames;
+ /// The minimum time in ms that has to pass between the playback of two consecutive mute cues.
+ static constexpr unsigned int iMuteCueDelay = 5000;
+
float *pfMicInput;
float *pfEchoInput;
diff --git a/src/mumble/AudioInput.ui b/src/mumble/AudioInput.ui
index 36c7f5858..8fc66b90f 100644
--- a/src/mumble/AudioInput.ui
+++ b/src/mumble/AudioInput.ui
@@ -772,26 +772,6 @@
<string>Misc</string>
</property>
<layout class="QGridLayout" name="_2">
- <item row="2" column="5">
- <widget class="QPushButton" name="qpbPushClickBrowseOff">
- <property name="toolTip">
- <string>Browse for off audio file</string>
- </property>
- <property name="text">
- <string>B&amp;rowse...</string>
- </property>
- </widget>
- </item>
- <item row="2" column="3">
- <widget class="QLabel" name="qlPushClickOff">
- <property name="text">
- <string>Off</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
<item row="1" column="3">
<widget class="QLabel" name="qlPushClickOn">
<property name="text">
@@ -802,42 +782,6 @@
</property>
</widget>
</item>
- <item row="1" column="6">
- <widget class="QPushButton" name="qpbPushClickPreview">
- <property name="toolTip">
- <string>Preview the audio cues</string>
- </property>
- <property name="whatsThis">
- <string>&lt;b&gt;Preview&lt;/b&gt;&lt;br/&gt;Plays the current &lt;i&gt;on&lt;/i&gt; sound followed by the current &lt;i&gt;off&lt;/i&gt; sound.</string>
- </property>
- <property name="text">
- <string>&amp;Preview</string>
- </property>
- </widget>
- </item>
- <item row="2" column="6">
- <widget class="QPushButton" name="qpbPushClickReset">
- <property name="toolTip">
- <string>Reset audio cue to default</string>
- </property>
- <property name="whatsThis">
- <string>&lt;b&gt;Reset&lt;/b&gt;&lt;br/&gt;Reset the paths for the files to their default.</string>
- </property>
- <property name="text">
- <string>R&amp;eset</string>
- </property>
- </widget>
- </item>
- <item row="1" column="5">
- <widget class="QPushButton" name="qpbPushClickBrowseOn">
- <property name="toolTip">
- <string>Browse for on audio file</string>
- </property>
- <property name="text">
- <string>&amp;Browse...</string>
- </property>
- </widget>
- </item>
<item row="1" column="4">
<widget class="QLineEdit" name="qlePushClickPathOn">
<property name="toolTip">
@@ -845,44 +789,34 @@
</property>
</widget>
</item>
- <item row="2" column="4">
- <widget class="QLineEdit" name="qlePushClickPathOff">
- <property name="toolTip">
- <string>Gets played when stopping to transmit</string>
+ <item row="4" column="0" colspan="2">
+ <widget class="QLabel" name="qliIdle">
+ <property name="text">
+ <string>Idle action</string>
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="qcbPushClick">
+ <item row="1" column="6">
+ <widget class="QPushButton" name="qpbPushClickPreview">
<property name="toolTip">
- <string>Audible audio cue when starting or stopping to transmit</string>
+ <string>Preview the audio cues</string>
</property>
<property name="whatsThis">
- <string>&lt;b&gt;This enables transmission audio cues.&lt;/b&gt;&lt;br /&gt;Setting this will give you a short audio beep when you start and stop transmitting.</string>
+ <string>&lt;b&gt;Preview&lt;/b&gt;&lt;br/&gt;Plays the current &lt;i&gt;on&lt;/i&gt; sound followed by the current &lt;i&gt;off&lt;/i&gt; sound.</string>
</property>
<property name="text">
- <string>Audio cue</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0" colspan="2">
- <widget class="QLabel" name="qliIdle">
- <property name="text">
- <string>Idle action</string>
+ <string>&amp;Preview</string>
</property>
</widget>
</item>
- <item row="4" column="4">
- <widget class="QCheckBox" name="qcbUndoIdleAction">
+ <item row="2" column="4">
+ <widget class="QLineEdit" name="qlePushClickPathOff">
<property name="toolTip">
- <string>The idle action will be reversed upon any key or mouse button input</string>
- </property>
- <property name="text">
- <string>Undo Idle action upon activity</string>
+ <string>Gets played when stopping to transmit</string>
</property>
</widget>
</item>
- <item row="3" column="4">
+ <item row="4" column="4">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QSpinBox" name="qsbIdle">
@@ -944,13 +878,103 @@
</item>
</layout>
</item>
- <item row="3" column="3">
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="qcbPushClick">
+ <property name="toolTip">
+ <string>Audible audio cue when starting or stopping to transmit</string>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;b&gt;This enables transmission audio cues.&lt;/b&gt;&lt;br /&gt;Setting this will give you a short audio beep when you start and stop transmitting.</string>
+ </property>
+ <property name="text">
+ <string>Audio cue</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="4">
+ <widget class="QCheckBox" name="qcbUndoIdleAction">
+ <property name="toolTip">
+ <string>The idle action will be reversed upon any key or mouse button input</string>
+ </property>
+ <property name="text">
+ <string>Undo Idle action upon activity</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="3">
+ <widget class="QLabel" name="qlPushClickOff">
+ <property name="text">
+ <string>Off</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="5">
+ <widget class="QPushButton" name="qpbPushClickBrowseOff">
+ <property name="toolTip">
+ <string>Browse for off audio file</string>
+ </property>
+ <property name="text">
+ <string>B&amp;rowse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="3">
<widget class="QLabel" name="qlIdle2">
<property name="text">
<string>after</string>
</property>
</widget>
</item>
+ <item row="2" column="6">
+ <widget class="QPushButton" name="qpbPushClickReset">
+ <property name="toolTip">
+ <string>Reset audio cue to default</string>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;b&gt;Reset&lt;/b&gt;&lt;br/&gt;Reset the paths for the files to their default.</string>
+ </property>
+ <property name="text">
+ <string>R&amp;eset</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <widget class="QPushButton" name="qpbPushClickBrowseOn">
+ <property name="toolTip">
+ <string>Browse for on audio file</string>
+ </property>
+ <property name="text">
+ <string>&amp;Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="qcbMuteCue">
+ <property name="text">
+ <string>Mute cue</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="4">
+ <widget class="QLineEdit" name="qleMuteCuePath"/>
+ </item>
+ <item row="3" column="5">
+ <widget class="QPushButton" name="qpbMuteCueBrowse">
+ <property name="text">
+ <string>Br&amp;owse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="6">
+ <widget class="QPushButton" name="qpbMuteCuePreview">
+ <property name="text">
+ <string>Pre&amp;view</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/mumble/Settings.cpp b/src/mumble/Settings.cpp
index aa85f4220..4bf80c107 100644
--- a/src/mumble/Settings.cpp
+++ b/src/mumble/Settings.cpp
@@ -162,6 +162,8 @@ QDataStream &operator>>(QDataStream &qds, ShortcutTarget &st) {
const QString Settings::cqsDefaultPushClickOn = QLatin1String(":/on.ogg");
const QString Settings::cqsDefaultPushClickOff = QLatin1String(":/off.ogg");
+const QString Settings::cqsDefaultMuteCue = QLatin1String(":/off.ogg");
+
OverlaySettings::OverlaySettings() {
bEnable = false;
@@ -336,6 +338,9 @@ Settings::Settings() {
qsTxAudioCueOn = cqsDefaultPushClickOn;
qsTxAudioCueOff = cqsDefaultPushClickOff;
+ bTxMuteCue = true;
+ qsTxMuteCue = cqsDefaultMuteCue;
+
bUserTop = true;
bWhisperFriends = false;
@@ -718,6 +723,8 @@ void Settings::load(QSettings *settings_ptr) {
LOAD(bTxAudioCue, "audio/pushclick");
LOAD(qsTxAudioCueOn, "audio/pushclickon");
LOAD(qsTxAudioCueOff, "audio/pushclickoff");
+ LOAD(bTxMuteCue, "audio/mutecue");
+ LOAD(qsTxMuteCue, "audio/mutecuepath");
LOAD(iQuality, "audio/quality");
LOAD(iMinLoudness, "audio/loudness");
LOAD(fVolume, "audio/volume");
@@ -1157,6 +1164,8 @@ void Settings::save() {
SAVE(bTxAudioCue, "audio/pushclick");
SAVE(qsTxAudioCueOn, "audio/pushclickon");
SAVE(qsTxAudioCueOff, "audio/pushclickoff");
+ SAVE(bTxMuteCue, "audio/mutecue");
+ SAVE(qsTxMuteCue, "audio/mutecuepath");
SAVE(iQuality, "audio/quality");
SAVE(iMinLoudness, "audio/loudness");
SAVE(fVolume, "audio/volume");
diff --git a/src/mumble/Settings.h b/src/mumble/Settings.h
index 18c5b9edb..285da8d5d 100644
--- a/src/mumble/Settings.h
+++ b/src/mumble/Settings.h
@@ -176,6 +176,10 @@ struct Settings {
QString qsTxAudioCueOn;
QString qsTxAudioCueOff;
+ bool bTxMuteCue;
+ static const QString cqsDefaultMuteCue;
+ QString qsTxMuteCue;
+
bool bTransmitPosition;
bool bMute, bDeaf;
bool bTTS;