From 4653effad8e45667752a6e7cc8413e5e94a3f6c0 Mon Sep 17 00:00:00 2001
From: Jonas Gutenschwager <spam.saikai@googlemail.com>
Date: Thu, 19 Jan 2023 15:13:23 +0100
Subject: [PATCH 1/2] add volume quicksetting with volume slider

---
 src/yuzu/main.cpp | 105 +++++++++++++++++++++++++++++++++++-----------
 src/yuzu/main.h   |   9 ++++
 2 files changed, 90 insertions(+), 24 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 571eacf9f4..b855416196 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -957,6 +957,38 @@ void GMainWindow::InitializeWidgets() {
     tas_label->setFocusPolicy(Qt::NoFocus);
     statusBar()->insertPermanentWidget(0, tas_label);
 
+    volume_popup = new QWidget(this);
+    volume_popup->setWindowFlags(Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::Popup);
+    volume_popup->setLayout(new QVBoxLayout());
+    volume_popup->setMinimumWidth(200);
+
+    volume_slider = new QSlider(Qt::Horizontal);
+    volume_slider->setObjectName(QStringLiteral("volume_slider"));
+    volume_slider->setMaximum(200);
+    volume_slider->setPageStep(5);
+    connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) {
+        Settings::values.audio_muted = false;
+        const auto volume = static_cast<u8>(percentage);
+        Settings::values.volume.SetValue(volume);
+        UpdateVolumeUI();
+    });
+    volume_popup->layout()->addWidget(volume_slider);
+
+    volume_button = new QPushButton();
+    volume_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
+    volume_button->setFocusPolicy(Qt::NoFocus);
+    volume_button->setCheckable(true);
+    UpdateVolumeUI();
+    connect(volume_button, &QPushButton::clicked, this, [&] {
+        UpdateVolumeUI();
+        volume_popup->setVisible(!volume_popup->isVisible());
+        QRect rect = volume_button->geometry();
+        QPoint bottomLeft = statusBar()->mapToGlobal(rect.topLeft());
+        bottomLeft.setY(bottomLeft.y() - volume_popup->geometry().height());
+        volume_popup->setGeometry(QRect(bottomLeft, QSize(rect.width(), rect.height())));
+    });
+    statusBar()->insertPermanentWidget(0, volume_button);
+
     // setup AA button
     aa_status_button = new QPushButton();
     aa_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
@@ -1124,30 +1156,9 @@ void GMainWindow::InitializeHotkeys() {
                      &GMainWindow::OnToggleAdaptingFilter);
     connect_shortcut(QStringLiteral("Change Docked Mode"), &GMainWindow::OnToggleDockedMode);
     connect_shortcut(QStringLiteral("Change GPU Accuracy"), &GMainWindow::OnToggleGpuAccuracy);
-    connect_shortcut(QStringLiteral("Audio Mute/Unmute"),
-                     [] { Settings::values.audio_muted = !Settings::values.audio_muted; });
-    connect_shortcut(QStringLiteral("Audio Volume Down"), [] {
-        const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue());
-        int step = 5;
-        if (current_volume <= 30) {
-            step = 2;
-        }
-        if (current_volume <= 6) {
-            step = 1;
-        }
-        Settings::values.volume.SetValue(std::max(current_volume - step, 0));
-    });
-    connect_shortcut(QStringLiteral("Audio Volume Up"), [] {
-        const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue());
-        int step = 5;
-        if (current_volume < 30) {
-            step = 2;
-        }
-        if (current_volume < 6) {
-            step = 1;
-        }
-        Settings::values.volume.SetValue(current_volume + step);
-    });
+    connect_shortcut(QStringLiteral("Audio Mute/Unmute"), &GMainWindow::OnMute);
+    connect_shortcut(QStringLiteral("Audio Volume Down"), &GMainWindow::OnDecreaseVolume);
+    connect_shortcut(QStringLiteral("Audio Volume Up"), &GMainWindow::OnIncreaseVolume);
     connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
         Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
     });
@@ -3462,6 +3473,39 @@ void GMainWindow::OnToggleGpuAccuracy() {
     UpdateGPUAccuracyButton();
 }
 
+void GMainWindow::OnMute() {
+    Settings::values.audio_muted = !Settings::values.audio_muted;
+    UpdateVolumeUI();
+}
+
+void GMainWindow::OnDecreaseVolume() {
+    Settings::values.audio_muted = false;
+    const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue());
+    int step = 5;
+    if (current_volume <= 30) {
+        step = 2;
+    }
+    if (current_volume <= 6) {
+        step = 1;
+    }
+    Settings::values.volume.SetValue(std::max(current_volume - step, 0));
+    UpdateVolumeUI();
+}
+
+void GMainWindow::OnIncreaseVolume() {
+    Settings::values.audio_muted = false;
+    const auto current_volume = static_cast<s32>(Settings::values.volume.GetValue());
+    int step = 5;
+    if (current_volume < 30) {
+        step = 2;
+    }
+    if (current_volume < 6) {
+        step = 1;
+    }
+    Settings::values.volume.SetValue(current_volume + step);
+    UpdateVolumeUI();
+}
+
 void GMainWindow::OnToggleAdaptingFilter() {
     auto filter = Settings::values.scaling_filter.GetValue();
     if (filter == Settings::ScalingFilter::LastFilter) {
@@ -3924,6 +3968,18 @@ void GMainWindow::UpdateAAText() {
     }
 }
 
+void GMainWindow::UpdateVolumeUI() {
+    const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
+    volume_slider->setValue(volume_value);
+    if (Settings::values.audio_muted) {
+        volume_button->setChecked(false);
+        volume_button->setText(tr("VOLUME: MUTE", "Volume percentage (e.g. 50%)"));
+    } else {
+        volume_button->setChecked(true);
+        volume_button->setText(tr("VOLUME: %1%", "Volume percentage (e.g. 50%)").arg(volume_value));
+    }
+}
+
 void GMainWindow::UpdateStatusButtons() {
     renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() ==
                                        Settings::RendererBackend::Vulkan);
@@ -3932,6 +3988,7 @@ void GMainWindow::UpdateStatusButtons() {
     UpdateDockedButton();
     UpdateFilterText();
     UpdateAAText();
+    UpdateVolumeUI();
 }
 
 void GMainWindow::UpdateUISettings() {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 0f61abc7ad..a23b373a5b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -37,6 +37,8 @@ class QLabel;
 class MultiplayerState;
 class QPushButton;
 class QProgressDialog;
+class QSlider;
+class QHBoxLayout;
 class WaitTreeWidget;
 enum class GameListOpenTarget;
 enum class GameListRemoveTarget;
@@ -312,6 +314,9 @@ private slots:
     void OnMenuRecentFile();
     void OnConfigure();
     void OnConfigureTas();
+    void OnDecreaseVolume();
+    void OnIncreaseVolume();
+    void OnMute();
     void OnTasStartStop();
     void OnTasRecord();
     void OnTasReset();
@@ -364,6 +369,7 @@ private:
     void UpdateAPIText();
     void UpdateFilterText();
     void UpdateAAText();
+    void UpdateVolumeUI();
     void UpdateStatusBar();
     void UpdateGPUAccuracyButton();
     void UpdateStatusButtons();
@@ -412,6 +418,9 @@ private:
     QPushButton* dock_status_button = nullptr;
     QPushButton* filter_status_button = nullptr;
     QPushButton* aa_status_button = nullptr;
+    QPushButton* volume_button = nullptr;
+    QWidget* volume_popup = nullptr;
+    QSlider* volume_slider = nullptr;
     QTimer status_bar_update_timer;
 
     std::unique_ptr<Config> config;

From 2a491f7aaa6977b7818b37a87fb8d2be8d1351c9 Mon Sep 17 00:00:00 2001
From: Jonas Gutenschwager <spam.saikai@googlemail.com>
Date: Sat, 4 Feb 2023 00:00:20 +0100
Subject: [PATCH 2/2] remove disambiguation argument from mute text

Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
---
 src/yuzu/main.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b855416196..c278620ab3 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -3973,7 +3973,7 @@ void GMainWindow::UpdateVolumeUI() {
     volume_slider->setValue(volume_value);
     if (Settings::values.audio_muted) {
         volume_button->setChecked(false);
-        volume_button->setText(tr("VOLUME: MUTE", "Volume percentage (e.g. 50%)"));
+        volume_button->setText(tr("VOLUME: MUTE"));
     } else {
         volume_button->setChecked(true);
         volume_button->setText(tr("VOLUME: %1%", "Volume percentage (e.g. 50%)").arg(volume_value));