diff --git a/src/mumble/ClientUser.cpp b/src/mumble/ClientUser.cpp
index c5b7141b1..c296031a0 100644
--- a/src/mumble/ClientUser.cpp
+++ b/src/mumble/ClientUser.cpp
@@ -19,6 +19,7 @@ ClientUser::ClientUser(QObject *p) : QObject(p),
tsState(Settings::Passive),
tLastTalkStateChange(false),
bLocalIgnore(false),
+ bLocalIgnoreTTS(false),
bLocalMute(false),
fPowerMin(0.0f),
fPowerMax(0.0f),
@@ -134,6 +135,8 @@ QString ClientUser::getFlagsString() const {
flags << ClientUser::tr("Deafened (server)");
if (bLocalIgnore)
flags << ClientUser::tr("Local Ignore (Text messages)");
+ if (bLocalIgnoreTTS)
+ flags << ClientUser::tr("Local Ignore (Text-To-Speech)");
if (bLocalMute)
flags << ClientUser::tr("Local Mute");
if (bSelfMute)
@@ -190,6 +193,10 @@ void ClientUser::setLocalIgnore(bool ignore) {
emit muteDeafStateChanged();
}
+void ClientUser::setLocalIgnoreTTS(bool ignoreTTS) {
+ bLocalIgnoreTTS = ignoreTTS;
+}
+
void ClientUser::setLocalMute(bool mute) {
if (bLocalMute == mute)
return;
diff --git a/src/mumble/ClientUser.h b/src/mumble/ClientUser.h
index 8089c773f..121ed3aef 100644
--- a/src/mumble/ClientUser.h
+++ b/src/mumble/ClientUser.h
@@ -21,6 +21,7 @@ class ClientUser : public QObject, public User {
Settings::TalkState tsState;
Timer tLastTalkStateChange;
bool bLocalIgnore;
+ bool bLocalIgnoreTTS;
bool bLocalMute;
float fPowerMin, fPowerMax;
@@ -67,6 +68,7 @@ class ClientUser : public QObject, public User {
void setDeaf(bool deaf);
void setSuppress(bool suppress);
void setLocalIgnore(bool ignore);
+ void setLocalIgnoreTTS(bool ignoreTTS);
void setLocalMute(bool mute);
void setSelfMute(bool mute);
void setSelfDeaf(bool deaf);
diff --git a/src/mumble/Database.cpp b/src/mumble/Database.cpp
index 408e11efb..89eb5bc90 100644
--- a/src/mumble/Database.cpp
+++ b/src/mumble/Database.cpp
@@ -137,6 +137,9 @@ Database::Database(const QString &dbname) {
execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `ignored` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `ignored_hash` ON `ignored`(`hash`)"));
+ execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `ignored_tts` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
+ execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `ignored_tts_hash` ON `ignored_tts`(`hash`)"));
+
execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `muted` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT)"));
execQueryAndLogFailure(query, QLatin1String("CREATE UNIQUE INDEX IF NOT EXISTS `muted_hash` ON `muted`(`hash`)"));
execQueryAndLogFailure(query, QLatin1String("CREATE TABLE IF NOT EXISTS `volume` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `hash` TEXT, `volume` FLOAT)"));
@@ -238,6 +241,26 @@ void Database::setLocalIgnored(const QString &hash, bool ignored) {
execQueryAndLogFailure(query);
}
+bool Database::isLocalIgnoredTTS(const QString &hash) {
+ QSqlQuery query(db);
+
+ query.prepare(QLatin1String("SELECT `hash` FROM `ignored_tts` WHERE `hash` = ?"));
+ query.addBindValue(hash);
+ execQueryAndLogFailure(query);
+ return query.next();
+}
+
+void Database::setLocalIgnoredTTS(const QString &hash, bool ignoredTTS) {
+ QSqlQuery query(db);
+
+ if (ignoredTTS)
+ query.prepare(QLatin1String("INSERT INTO `ignored_tts` (`hash`) VALUES (?)"));
+ else
+ query.prepare(QLatin1String("DELETE FROM `ignored_tts` WHERE `hash` = ?"));
+ query.addBindValue(hash);
+ execQueryAndLogFailure(query);
+}
+
bool Database::isLocalMuted(const QString &hash) {
QSqlQuery query(db);
diff --git a/src/mumble/Database.h b/src/mumble/Database.h
index abb51a1c2..3e626c044 100644
--- a/src/mumble/Database.h
+++ b/src/mumble/Database.h
@@ -37,6 +37,9 @@ class Database : public QObject {
bool isLocalIgnored(const QString &hash);
void setLocalIgnored(const QString &hash, bool ignored);
+ bool isLocalIgnoredTTS(const QString &hash);
+ void setLocalIgnoredTTS(const QString &hash, bool ignoredTTS);
+
bool isLocalMuted(const QString &hash);
void setLocalMuted(const QString &hash, bool muted);
diff --git a/src/mumble/Log.cpp b/src/mumble/Log.cpp
index be7b2429e..7a6517439 100644
--- a/src/mumble/Log.cpp
+++ b/src/mumble/Log.cpp
@@ -324,15 +324,15 @@ QString Log::formatChannel(::Channel *c) {
return QString::fromLatin1("%2").arg(c->iId).arg(c->qsName.toHtmlEscaped()).arg(QString::fromLatin1(g.sh->qbaDigest.toBase64()));
}
-void Log::logOrDefer(Log::MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS) {
+void Log::logOrDefer(Log::MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS, bool ignoreTTS) {
if (g.l) {
// log directly as it seems the log-UI has been set-up already
- g.l->log(mt, console, terse, ownMessage, overrideTTS);
+ g.l->log(mt, console, terse, ownMessage, overrideTTS, ignoreTTS);
} else {
// defer the log
QMutexLocker mLock(&Log::qmDeferredLogs);
- qvDeferredLogs.append(LogMessage(mt, console, terse, ownMessage, overrideTTS));
+ qvDeferredLogs.append(LogMessage(mt, console, terse, ownMessage, overrideTTS, ignoreTTS));
}
}
@@ -494,7 +494,7 @@ QString Log::validHtml(const QString &html, QTextCursor *tc) {
}
}
-void Log::log(MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS) {
+void Log::log(MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS, bool ignoreTTS) {
QDateTime dt = QDateTime::currentDateTime();
int ignore = qmIgnore.value(mt);
@@ -601,7 +601,7 @@ void Log::log(MsgType mt, const QString &console, const QString &terse, bool own
}
// Message notification with Text-To-Speech
- if (g.s.bDeaf || !g.s.bTTS || !(flags & Settings::LogTTS)) {
+ if (g.s.bDeaf || !g.s.bTTS || !(flags & Settings::LogTTS) || ignoreTTS) {
return;
}
@@ -658,7 +658,7 @@ void Log::processDeferredLogs() {
while (!qvDeferredLogs.isEmpty()) {
LogMessage msg = qvDeferredLogs.takeFirst();
- log(msg.mt, msg.console, msg.terse, msg.ownMessage, msg.overrideTTS);
+ log(msg.mt, msg.console, msg.terse, msg.ownMessage, msg.overrideTTS, msg.ignoreTTS);
}
}
@@ -682,8 +682,8 @@ void Log::postQtNotification(MsgType mt, const QString &plain) {
}
}
-LogMessage::LogMessage(Log::MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS) : mt(mt), console(console),
- terse(terse), ownMessage(ownMessage), overrideTTS(overrideTTS) {
+LogMessage::LogMessage(Log::MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS, bool ignoreTTS) : mt(mt), console(console),
+ terse(terse), ownMessage(ownMessage), overrideTTS(overrideTTS), ignoreTTS(ignoreTTS) {
}
LogDocument::LogDocument(QObject *p)
diff --git a/src/mumble/Log.h b/src/mumble/Log.h
index 46814927e..cbd83190d 100644
--- a/src/mumble/Log.h
+++ b/src/mumble/Log.h
@@ -90,9 +90,9 @@ class Log : public QObject {
static QString formatChannel(::Channel *c);
/// Either defers the LogMessage or defers it, depending on whether Global::l is created already
/// (if it is, it is used to directly log the msg)
- static void logOrDefer(Log::MsgType mt, const QString &console, const QString &terse=QString(), bool ownMessage = false, const QString &overrideTTS=QString());
+ static void logOrDefer(Log::MsgType mt, const QString &console, const QString &terse=QString(), bool ownMessage = false, const QString &overrideTTS=QString(), bool ignoreTTS = false);
public slots:
- void log(MsgType mt, const QString &console, const QString &terse=QString(), bool ownMessage = false, const QString &overrideTTS=QString());
+ void log(MsgType mt, const QString &console, const QString &terse=QString(), bool ownMessage = false, const QString &overrideTTS=QString(), bool ignoreTTS = false);
/// Logs LogMessages that have been deferred so far
void processDeferredLogs();
};
@@ -104,9 +104,10 @@ class LogMessage {
QString terse;
bool ownMessage;
QString overrideTTS;
+ bool ignoreTTS;
LogMessage() = default;
- LogMessage(Log::MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS);
+ LogMessage(Log::MsgType mt, const QString &console, const QString &terse, bool ownMessage, const QString &overrideTTS, bool ignoreTTS);
};
class LogDocument : public QTextDocument {
diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp
index a9cb3d015..815d8003c 100644
--- a/src/mumble/MainWindow.cpp
+++ b/src/mumble/MainWindow.cpp
@@ -1526,6 +1526,8 @@ void MainWindow::qmUser_aboutToShow() {
qmUser->addAction(qaUserPrioritySpeaker);
qmUser->addAction(qaUserLocalMute);
qmUser->addAction(qaUserLocalIgnore);
+ if (g.s.bTTS)
+ qmUser->addAction(qaUserLocalIgnoreTTS);
qmUser->addAction(qaUserLocalVolume);
if (isSelf)
@@ -1585,6 +1587,7 @@ void MainWindow::qmUser_aboutToShow() {
qaUserLocalMute->setEnabled(false);
qaUserLocalVolume->setEnabled(false);
qaUserLocalIgnore->setEnabled(false);
+ qaUserLocalIgnoreTTS->setEnabled(false);
qaUserCommentReset->setEnabled(false);
qaUserTextureReset->setEnabled(false);
qaUserCommentView->setEnabled(false);
@@ -1595,6 +1598,7 @@ void MainWindow::qmUser_aboutToShow() {
qaUserLocalMute->setEnabled(! isSelf);
qaUserLocalVolume->setEnabled(! isSelf);
qaUserLocalIgnore->setEnabled(! isSelf);
+ qaUserLocalIgnoreTTS->setEnabled(! isSelf);
// If the server's version is less than 1.4.0 it won't support the new permission to reset a comment/avatar, so fall back to the old method
if (g.sh->uiVersion < 0x010400) {
qaUserCommentReset->setEnabled(! p->qbaCommentHash.isEmpty() && (g.pPermissions & (ChanACL::Move | ChanACL::Write)));
@@ -1610,6 +1614,7 @@ void MainWindow::qmUser_aboutToShow() {
qaUserPrioritySpeaker->setChecked(p->bPrioritySpeaker);
qaUserLocalMute->setChecked(p->bLocalMute);
qaUserLocalIgnore->setChecked(p->bLocalIgnore);
+ qaUserLocalIgnoreTTS->setChecked(p->bLocalIgnoreTTS);
}
updateMenuPermissions();
}
@@ -1690,6 +1695,18 @@ void MainWindow::on_qaUserLocalIgnore_triggered() {
g.db->setLocalIgnored(p->qsHash, ignored);
}
+void MainWindow::on_qaUserLocalIgnoreTTS_triggered() {
+ ClientUser *p = getContextMenuUser();
+ if (!p)
+ return;
+
+ bool ignoredTTS = qaUserLocalIgnoreTTS->isChecked();
+
+ p->setLocalIgnoreTTS(ignoredTTS);
+ if (! p->qsHash.isEmpty())
+ g.db->setLocalIgnoredTTS(p->qsHash, ignoredTTS);
+}
+
void MainWindow::on_qaUserLocalVolume_triggered() {
ClientUser *p = getContextMenuUser();
if (!p) {
diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h
index 51060e90c..41e5f6efe 100644
--- a/src/mumble/MainWindow.h
+++ b/src/mumble/MainWindow.h
@@ -206,6 +206,7 @@ class MainWindow : public QMainWindow, public MessageHandler, public Ui::MainWin
void on_qaSelfPrioritySpeaker_triggered();
void on_qaUserPrioritySpeaker_triggered();
void on_qaUserLocalIgnore_triggered();
+ void on_qaUserLocalIgnoreTTS_triggered();
void on_qaUserLocalMute_triggered();
void on_qaUserLocalVolume_triggered();
void on_qaUserTextMessage_triggered();
diff --git a/src/mumble/MainWindow.ui b/src/mumble/MainWindow.ui
index ed2f28f96..e5891e264 100644
--- a/src/mumble/MainWindow.ui
+++ b/src/mumble/MainWindow.ui
@@ -955,6 +955,20 @@ the channel's context menu.
Joins the channel of this user.
+
+
+ true
+
+
+ Disable Text-To-Speech
+
+
+ Locally disable Text-To-Speech for this user's text chat messages.
+
+
+ Silently disables Text-To-Speech for all text messages from the user.
+
+
diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp
index dd9c45fe9..df134144f 100644
--- a/src/mumble/Messages.cpp
+++ b/src/mumble/Messages.cpp
@@ -504,6 +504,8 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) {
pDst->setLocalMute(true);
if (g.db->isLocalIgnored(pDst->qsHash))
pDst->setLocalIgnore(true);
+ if (g.db->isLocalIgnoredTTS(pDst->qsHash))
+ pDst->setLocalIgnoreTTS(true);
pDst->fLocalVolume = g.db->getUserLocalVolume(pDst->qsHash);
}
@@ -909,7 +911,8 @@ void MainWindow::msgTextMessage(const MumbleProto::TextMessage &msg) {
tr("%2%1: %3").arg(name).arg(target).arg(u8(msg.message())),
tr("Message from %1").arg(plainName),
false,
- overrideTTS.isNull() ? QString() : overrideTTS);
+ overrideTTS.isNull() ? QString() : overrideTTS,
+ pSrc->bLocalIgnoreTTS);
}
/// This message is being received when the server informs the client about the access control list (ACL) for