From d8100e5b42660f5580052bc47305d47544f6d268 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Fri, 28 Aug 2020 10:25:00 +0200 Subject: [PATCH 1/3] FEAT(code): Emit signal on volume adjustment A ClientUser object will now emit a signal every time its local volume adjustment is being changed. --- src/mumble/AudioOutput.cpp | 2 +- src/mumble/ClientUser.cpp | 12 +++++++++++- src/mumble/ClientUser.h | 9 ++++++++- src/mumble/Messages.cpp | 2 +- src/mumble/UserLocalVolumeDialog.cpp | 6 +++--- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/mumble/AudioOutput.cpp b/src/mumble/AudioOutput.cpp index a62739790..dd7b7f542 100644 --- a/src/mumble/AudioOutput.cpp +++ b/src/mumble/AudioOutput.cpp @@ -518,7 +518,7 @@ bool AudioOutput::mix(void *outbuff, unsigned int frameCount) { AudioOutputSpeech *speech = qobject_cast(aop); if (speech) { const ClientUser *user = speech->p; - volumeAdjustment *= user->fLocalVolume; + volumeAdjustment *= user->getLocalVolumeAdjustments(); if (user->cChannel && ChannelListener::isListening(g.uiSession, user->cChannel->iId) && (speech->ucFlags & SpeechFlags::Listen)) { // We are receiving this audio packet only because we are listening to the channel diff --git a/src/mumble/ClientUser.cpp b/src/mumble/ClientUser.cpp index 94a35312c..33815039c 100644 --- a/src/mumble/ClientUser.cpp +++ b/src/mumble/ClientUser.cpp @@ -24,11 +24,14 @@ ClientUser::ClientUser(QObject *p) : QObject(p), fPowerMin(0.0f), fPowerMax(0.0f), fAverageAvailable(0.0f), - fLocalVolume(1.0f), iFrames(0), iSequence(0) { } +float ClientUser::getLocalVolumeAdjustments() const { + return m_localVolume; +} + ClientUser *ClientUser::get(unsigned int uiSession) { QReadLocker lock(&c_qrwlUsers); ClientUser *p = c_qmUsers.value(uiSession); @@ -239,6 +242,13 @@ void ClientUser::setRecording(bool recording) { emit recordingStateChanged(); } +void ClientUser::setLocalVolumeAdjustment(float adjustment) { + float oldAdjustment = m_localVolume; + m_localVolume = adjustment; + + emit localVolumeAdjustmentsChanged(m_localVolume, oldAdjustment); +} + bool ClientUser::lessThanOverlay(const ClientUser *first, const ClientUser *second) { if (g.s.os.osSort == OverlaySettings::LastStateChange) { // Talkers above non-talkers diff --git a/src/mumble/ClientUser.h b/src/mumble/ClientUser.h index 08cb43792..f42c8071b 100644 --- a/src/mumble/ClientUser.h +++ b/src/mumble/ClientUser.h @@ -17,6 +17,10 @@ class ClientUser : public QObject, public User { private: Q_OBJECT Q_DISABLE_COPY(ClientUser) + + protected: + float m_localVolume = 1.0f; + public: Settings::TalkState tsState; Timer tLastTalkStateChange; @@ -26,7 +30,6 @@ class ClientUser : public QObject, public User { float fPowerMin, fPowerMax; float fAverageAvailable; - float fLocalVolume; int iFrames; int iSequence; @@ -37,6 +40,8 @@ class ClientUser : public QObject, public User { QString getFlagsString() const; ClientUser(QObject *p = nullptr); + float getLocalVolumeAdjustments() const; + /** * Determines whether a user is active or not * A user is active when it is currently speaking or when the user has @@ -74,11 +79,13 @@ class ClientUser : public QObject, public User { void setSelfDeaf(bool deaf); void setPrioritySpeaker(bool priority); void setRecording(bool recording); + void setLocalVolumeAdjustment(float adjustment); signals: void talkingStateChanged(); void muteDeafStateChanged(); void prioritySpeakerStateChanged(); void recordingStateChanged(); + void localVolumeAdjustmentsChanged(float newAdjustment, float oldAdjustment); }; #endif diff --git a/src/mumble/Messages.cpp b/src/mumble/Messages.cpp index 7bee9e7be..79faefbb8 100644 --- a/src/mumble/Messages.cpp +++ b/src/mumble/Messages.cpp @@ -522,7 +522,7 @@ void MainWindow::msgUserState(const MumbleProto::UserState &msg) { pDst->setLocalIgnore(true); if (g.db->isLocalIgnoredTTS(pDst->qsHash)) pDst->setLocalIgnoreTTS(true); - pDst->fLocalVolume = g.db->getUserLocalVolume(pDst->qsHash); + pDst->setLocalVolumeAdjustment(g.db->getUserLocalVolume(pDst->qsHash)); } if (msg.has_self_deaf() || msg.has_self_mute()) { diff --git a/src/mumble/UserLocalVolumeDialog.cpp b/src/mumble/UserLocalVolumeDialog.cpp index e87323605..2975a830f 100644 --- a/src/mumble/UserLocalVolumeDialog.cpp +++ b/src/mumble/UserLocalVolumeDialog.cpp @@ -60,7 +60,7 @@ UserLocalVolumeDialog::UserLocalVolumeDialog(unsigned int sessionId, if (user) { QString title = tr("Adjusting local volume for %1").arg(user->qsName); setWindowTitle(title); - qsUserLocalVolume->setValue(qRound(log2(user->fLocalVolume) * 6.0)); + qsUserLocalVolume->setValue(qRound(log2(user->getLocalVolumeAdjustments()) * 6.0)); m_originalVolumeAdjustmentDecibel = qsUserLocalVolume->value(); } @@ -92,7 +92,7 @@ void UserLocalVolumeDialog::on_qsUserLocalVolume_valueChanged(int value) { ClientUser *user = ClientUser::get(m_clientSession); if (user) { // Decibel formula: +6db = *2 - user->fLocalVolume = static_cast(pow(2.0, qsUserLocalVolume->value() / 6.0)); + user->setLocalVolumeAdjustment(static_cast(pow(2.0, qsUserLocalVolume->value() / 6.0))); } } @@ -108,7 +108,7 @@ void UserLocalVolumeDialog::on_qbbUserLocalVolume_clicked(QAbstractButton *butto ClientUser *user = ClientUser::get(m_clientSession); if (user) { if (!user->qsHash.isEmpty()) { - g.db->setUserLocalVolume(user->qsHash, user->fLocalVolume); + g.db->setUserLocalVolume(user->qsHash, user->getLocalVolumeAdjustments()); } else { g.mw->logChangeNotPermanent(QObject::tr("Local Volume Adjustment..."), user); } From 72deaf940108540d5c39be30ed88c9cc8e580dc0 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 27 Aug 2020 18:02:21 +0200 Subject: [PATCH 2/3] FEAT(client, mainwindow): Show volume adjustments This feature optionally allows users to display the set volume adjustments next to the user's/listener's name. It will only be shown if it is not equal to 0 dB (aka: it is actually having an effect). By default this option is enabled since it is only visible if volume adjustments are set up anyways. --- src/mumble/LookConfig.cpp | 2 + src/mumble/LookConfig.ui | 80 ++++++++++++++++++++++----------------- src/mumble/Settings.cpp | 3 ++ src/mumble/Settings.h | 1 + src/mumble/TalkingUI.cpp | 23 +++++++---- src/mumble/TalkingUI.h | 2 + src/mumble/UserModel.cpp | 46 ++++++++++++++++++++-- src/mumble/UserModel.h | 3 ++ 8 files changed, 114 insertions(+), 46 deletions(-) diff --git a/src/mumble/LookConfig.cpp b/src/mumble/LookConfig.cpp index de8d0a33c..aaf13faf9 100644 --- a/src/mumble/LookConfig.cpp +++ b/src/mumble/LookConfig.cpp @@ -189,6 +189,7 @@ void LookConfig::load(const Settings &r) { loadCheckBox(qcbHideTray, r.bHideInTray); loadCheckBox(qcbStateInTray, r.bStateInTray); loadCheckBox(qcbShowUserCount, r.bShowUserCount); + loadCheckBox(qcbShowVolumeAdjustments, r.bShowVolumeAdjustments); loadCheckBox(qcbShowContextMenuInMenuBar, r.bShowContextMenuInMenuBar); loadCheckBox(qcbShowTransmitModeComboBox, r.bShowTransmitModeComboBox); loadCheckBox(qcbHighContrast, r.bHighContrast); @@ -249,6 +250,7 @@ void LookConfig::save() const { s.bHideInTray = qcbHideTray->isChecked(); s.bStateInTray = qcbStateInTray->isChecked(); s.bShowUserCount = qcbShowUserCount->isChecked(); + s.bShowVolumeAdjustments = qcbShowVolumeAdjustments->isChecked(); s.bShowContextMenuInMenuBar = qcbShowContextMenuInMenuBar->isChecked(); s.bShowTransmitModeComboBox = qcbShowTransmitModeComboBox->isChecked(); s.bHighContrast = qcbHighContrast->isChecked(); diff --git a/src/mumble/LookConfig.ui b/src/mumble/LookConfig.ui index 2fbb2a663..94dc8d4a9 100644 --- a/src/mumble/LookConfig.ui +++ b/src/mumble/LookConfig.ui @@ -7,7 +7,7 @@ 0 0 728 - 1120 + 1148 @@ -671,6 +671,33 @@ Channel Tree + + + + Filter automatically hides empty channels + + + + + + + When to automatically expand channels + + + This sets which channels to automatically expand. <i>None</i> and <i>All</i> will expand no or all channels, while <i>Only with users</i> will expand and collapse channels as users join and leave them. + + + + + + + This changes the behavior when moving users. + + + This sets the behavior of user drags; it can be used to prevent accidental dragging. <i>Move</i> moves the user without prompting. <i>Do Nothing</i> does nothing and prints an error message. <i>Ask</i> uses a message box to confirm if you really wanted to move the user. + + + @@ -678,13 +705,6 @@ - - - - Expand - - - @@ -692,6 +712,20 @@ + + + + Use selected item as the chat bar target + + + + + + + Expand + + + @@ -726,36 +760,12 @@ - - - Use selected item as the chat bar target - - - - - + - When to automatically expand channels + Show the local volume adjustment for each user (if any). - - This sets which channels to automatically expand. <i>None</i> and <i>All</i> will expand no or all channels, while <i>Only with users</i> will expand and collapse channels as users join and leave them. - - - - - - Filter automatically hides empty channels - - - - - - - This changes the behavior when moving users. - - - This sets the behavior of user drags; it can be used to prevent accidental dragging. <i>Move</i> moves the user without prompting. <i>Do Nothing</i> does nothing and prints an error message. <i>Ask</i> uses a message box to confirm if you really wanted to move the user. + Show volume adjustments diff --git a/src/mumble/Settings.cpp b/src/mumble/Settings.cpp index 461822373..c9eea0b42 100644 --- a/src/mumble/Settings.cpp +++ b/src/mumble/Settings.cpp @@ -356,6 +356,7 @@ Settings::Settings() { bStateInTray = true; bUsage = true; bShowUserCount = false; + bShowVolumeAdjustments = true; bChatBarUseSelection = false; bFilterHidesEmptyChannels = true; bFilterActive = false; @@ -1176,6 +1177,8 @@ void Settings::save() { SAVELOAD(bStateInTray, "ui/stateintray"); SAVELOAD(bUsage, "ui/usage"); SAVELOAD(bShowUserCount, "ui/showusercount"); + SAVELOAD(bShowVolumeAdjustments, "ui/showVolumeAdjustments"); + SAVELOAD(bShowVolumeAdjustments, "ui/showVolumeAdjustments"); SAVELOAD(bChatBarUseSelection, "ui/chatbaruseselection"); SAVELOAD(bFilterHidesEmptyChannels, "ui/filterhidesemptychannels"); SAVELOAD(bFilterActive, "ui/filteractive"); diff --git a/src/mumble/Settings.h b/src/mumble/Settings.h index 308c50367..17dc1cb6d 100644 --- a/src/mumble/Settings.h +++ b/src/mumble/Settings.h @@ -322,6 +322,7 @@ struct Settings { bool bStateInTray; bool bUsage; bool bShowUserCount; + bool bShowVolumeAdjustments; bool bChatBarUseSelection; bool bFilterHidesEmptyChannels; bool bFilterActive; diff --git a/src/mumble/TalkingUI.cpp b/src/mumble/TalkingUI.cpp index ff279126f..ac7c93e15 100644 --- a/src/mumble/TalkingUI.cpp +++ b/src/mumble/TalkingUI.cpp @@ -306,10 +306,7 @@ void TalkingUI::addUser(const ClientUser *user) { // We also verify whether the name for that user matches up (if it is contained in m_entries) in case // a user didn't get removed from the map but its ID got reused by a new client. - // Strip HTML from the displayed name - const QString name = QTextDocumentFragment::fromHtml(m_entries[user->uiSession].name->text()).toPlainText(); - - nameMatches = name == user->qsName; + nameMatches = m_entries[user->uiSession].qsName == user->qsName; if (!nameMatches) { // Hide the stale user @@ -342,11 +339,12 @@ void TalkingUI::addUser(const ClientUser *user) { background->setProperty("userName", user->qsName); QLabel *name = new QLabel(background); + const QString displayString = UserModel::createDisplayString(*user, false, nullptr); if (isSelf) { // Indicate self by bold name - name->setText(QString::fromLatin1("%1").arg(user->qsName)); + name->setText(QString::fromLatin1("%1").arg(displayString)); } else { - name->setText(user->qsName); + name->setText(displayString); } QLabel *icon = new QLabel(background); @@ -354,7 +352,7 @@ void TalkingUI::addUser(const ClientUser *user) { icon->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); // As a default use the passive state - Entry entry = {icon, name, background, nullptr, user->uiSession, Settings::Passive}; + Entry entry = {icon, name, background, nullptr, user->uiSession, Settings::Passive, user->qsName}; setTalkingIcon(entry); m_entries.insert(user->uiSession, entry); @@ -374,6 +372,8 @@ void TalkingUI::addUser(const ClientUser *user) { m_timers.insert(user->uiSession, timer); + QObject::connect(user, &ClientUser::localVolumeAdjustmentsChanged, this, &TalkingUI::on_userLocalVolumeAdjustmentsChanged); + // If this user is currently selected, mark him/her as such if (g.mw && g.mw->pmModel && g.mw->pmModel->getSelectedUser() == user) { if (m_entries.contains(user->uiSession)) { @@ -862,3 +862,12 @@ void TalkingUI::on_muteDeafStateChanged() { } } +void TalkingUI::on_userLocalVolumeAdjustmentsChanged(float, float) { + ClientUser *user = qobject_cast(sender()); + + if (user && m_entries.contains(user->uiSession)) { + Entry entry = m_entries[user->uiSession]; + + entry.name->setText(UserModel::createDisplayString(*user, false, nullptr)); + } +} diff --git a/src/mumble/TalkingUI.h b/src/mumble/TalkingUI.h index e1d78e4a8..f34e76034 100644 --- a/src/mumble/TalkingUI.h +++ b/src/mumble/TalkingUI.h @@ -35,6 +35,7 @@ struct Entry { QLabel *statusIcons; unsigned int userSession; Settings::TalkState talkingState; + QString qsName; }; /// The talking UI is a widget that will display the users you are currently @@ -142,6 +143,7 @@ class TalkingUI : public QWidget { void on_settingsChanged(); void on_clientDisconnected(unsigned int userSession); void on_muteDeafStateChanged(); + void on_userLocalVolumeAdjustmentsChanged(float newAdjustment, float oldAdjustment); }; #endif // MUMBLE_MUMBLE_TALKINGUI_H_ diff --git a/src/mumble/UserModel.cpp b/src/mumble/UserModel.cpp index 8051f263f..cbc5ef050 100644 --- a/src/mumble/UserModel.cpp +++ b/src/mumble/UserModel.cpp @@ -454,11 +454,12 @@ QVariant UserModel::data(const QModelIndex &idx, int role) const { break; case Qt::DisplayRole: if (idx.column() == 0) { - if (! p->qsFriendName.isEmpty() && (p->qsFriendName.toLower() != p->qsName.toLower())) - return QString::fromLatin1("%1 (%2)").arg(p->qsName).arg(p->qsFriendName); - else - return p->qsName; + // Get the channel the user/listener is in + const Channel *parentChannel = item->parent ? item->parent->cChan : nullptr; + + return createDisplayString(*p, item->isListener, parentChannel); } + // Most of the following icons are for non-listeners (as listeners are merely proxies) only // but in order to not change the order of the icons, the condition is added to each case // individually instead of checking it up front. @@ -1847,3 +1848,40 @@ void UserModel::updateOverlay() const { #endif g.lcd->updateUserView(); } + + +QString UserModel::createDisplayString(const ClientUser &user, bool isChannelListener, const Channel *parentChannel) { + // Get the configured volume adjustment. Depending on whether + // this display string is for a ChannelListener or a regular user, we have to fetch + // the volume adjustment differently. + float volumeAdjustment = isChannelListener && parentChannel + ? ChannelListener::getListenerLocalVolumeAdjustment(parentChannel->iId) : user.getLocalVolumeAdjustments(); + + // Transform the adjustment into dB + // *2 == 6 dB + int localVolumeDecibel = std::round(log2f(volumeAdjustment) * 6); + + // Create a friend-tag + QString friendTag; + if (!user.qsFriendName.isEmpty() && user.qsName.compare(user.qsFriendName, Qt::CaseInsensitive) != 0) { + friendTag = QString::fromLatin1("(%2)").arg(user.qsFriendName); + } + + // Create a tag that indicates the volume adjustments + QString volumeTag; + if (std::abs(localVolumeDecibel) > 0 && g.s.bShowVolumeAdjustments) { + volumeTag = QString::asprintf("|%+d|", localVolumeDecibel); + } + + QString displayString = user.qsName; + + if (!friendTag.isEmpty()) { + displayString += " " + friendTag; + } + + if (!volumeTag.isEmpty()) { + displayString += " " + volumeTag; + } + + return displayString; +} diff --git a/src/mumble/UserModel.h b/src/mumble/UserModel.h index 339d1bb48..53bfca532 100644 --- a/src/mumble/UserModel.h +++ b/src/mumble/UserModel.h @@ -186,6 +186,9 @@ class UserModel : public QAbstractItemModel { unsigned int uiSessionComment; int iChannelDescription; + + + static QString createDisplayString(const ClientUser &user, bool isChannelListener, const Channel *parentChannel); public slots: /// Invalidates the model data of the ClientUser triggering this slot. void userStateChanged(); From 7c1f1c9d775baba507db8c25224bf24d6ba39361 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Thu, 27 Aug 2020 18:04:40 +0200 Subject: [PATCH 3/3] Translation update Updating 'mumble_en.ts'... Found 1893 source text(s) (2 new and 1891 already existing) --- src/mumble/mumble_en.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mumble/mumble_en.ts b/src/mumble/mumble_en.ts index e0abd0ae2..b7dca49d4 100644 --- a/src/mumble/mumble_en.ts +++ b/src/mumble/mumble_en.ts @@ -4267,6 +4267,14 @@ The setting only applies for new messages, the already shown ones will retain th Silent user lifetime + + Show the local volume adjustment for each user (if any). + + + + Show volume adjustments + + MainWindow