From 15243093c40815d0e610bab02349a8bb40d7b227 Mon Sep 17 00:00:00 2001 From: spycrab Date: Wed, 21 Jun 2017 10:26:06 +0200 Subject: [PATCH 1/2] Qt: Implement missing settings --- Source/Core/DolphinQt2/HotkeyScheduler.cpp | 8 +++---- Source/Core/DolphinQt2/Settings.cpp | 27 ++++++++++++++++++++++ Source/Core/DolphinQt2/Settings.h | 7 ++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/Source/Core/DolphinQt2/HotkeyScheduler.cpp b/Source/Core/DolphinQt2/HotkeyScheduler.cpp index 3be862f8e1..90305b1a09 100644 --- a/Source/Core/DolphinQt2/HotkeyScheduler.cpp +++ b/Source/Core/DolphinQt2/HotkeyScheduler.cpp @@ -159,18 +159,18 @@ void HotkeyScheduler::Run() if (IsHotkey(HK_EXIT)) emit ExitHotkey(); + auto& settings = Settings::Instance(); + // Volume if (IsHotkey(HK_VOLUME_DOWN)) - AudioCommon::DecreaseVolume(3); + settings.DecreaseVolume(3); if (IsHotkey(HK_VOLUME_UP)) - AudioCommon::IncreaseVolume(3); + settings.IncreaseVolume(3); if (IsHotkey(HK_VOLUME_TOGGLE_MUTE)) AudioCommon::ToggleMuteVolume(); - auto& settings = Settings::Instance(); - // Wiimote if (settings.IsBluetoothPassthroughEnabled()) { diff --git a/Source/Core/DolphinQt2/Settings.cpp b/Source/Core/DolphinQt2/Settings.cpp index bac3a4143f..5e29d14079 100644 --- a/Source/Core/DolphinQt2/Settings.cpp +++ b/Source/Core/DolphinQt2/Settings.cpp @@ -5,6 +5,7 @@ #include #include +#include "AudioCommon/AudioCommon.h" #include "Common/FileSearch.h" #include "Common/FileUtil.h" #include "Common/StringUtil.h" @@ -230,6 +231,32 @@ bool Settings::GetHideCursor() const return SConfig::GetInstance().bHideCursor; } +int Settings::GetVolume() const +{ + return SConfig::GetInstance().m_Volume; +} + +void Settings::SetVolume(int volume) +{ + if (GetVolume() != volume) + { + SConfig::GetInstance().m_Volume = volume; + emit VolumeChanged(volume); + } +} + +void Settings::IncreaseVolume(int volume) +{ + AudioCommon::IncreaseVolume(volume); + emit VolumeChanged(GetVolume()); +} + +void Settings::DecreaseVolume(int volume) +{ + AudioCommon::DecreaseVolume(volume); + emit VolumeChanged(GetVolume()); +} + bool& Settings::BannerVisible() const { return SConfig::GetInstance().m_showBannerColumn; diff --git a/Source/Core/DolphinQt2/Settings.h b/Source/Core/DolphinQt2/Settings.h index d7ee40246b..786add0fa5 100644 --- a/Source/Core/DolphinQt2/Settings.h +++ b/Source/Core/DolphinQt2/Settings.h @@ -75,6 +75,12 @@ public: void SetHideCursor(bool hide_cursor); bool GetHideCursor() const; + // Audio + int GetVolume() const; + void SetVolume(int volume); + void IncreaseVolume(int volume); + void DecreaseVolume(int volume); + // Columns bool& BannerVisible() const; bool& CountryVisible() const; @@ -116,6 +122,7 @@ signals: void PathAdded(const QString&); void PathRemoved(const QString&); void HideCursorChanged(); + void VolumeChanged(int volume); private: Settings(); From ba3df3db056b44588b425db272f9c61f0c4efa07 Mon Sep 17 00:00:00 2001 From: spycrab Date: Wed, 21 Jun 2017 10:27:21 +0200 Subject: [PATCH 2/2] Qt/Settings: Implement audio pane --- Source/Core/DolphinQt2/CMakeLists.txt | 1 + .../Core/DolphinQt2/Config/SettingsWindow.cpp | 11 + .../Core/DolphinQt2/Config/SettingsWindow.h | 4 + Source/Core/DolphinQt2/DolphinQt2.vcxproj | 3 + Source/Core/DolphinQt2/MainWindow.cpp | 5 + Source/Core/DolphinQt2/Settings/AudioPane.cpp | 244 ++++++++++++++++++ Source/Core/DolphinQt2/Settings/AudioPane.h | 59 +++++ 7 files changed, 327 insertions(+) create mode 100644 Source/Core/DolphinQt2/Settings/AudioPane.cpp create mode 100644 Source/Core/DolphinQt2/Settings/AudioPane.h diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index ac9897c251..10b26d5fe4 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -51,6 +51,7 @@ set(SRCS QtUtils/DoubleClickEventFilter.cpp QtUtils/ElidedButton.cpp QtUtils/WindowActivationEventFilter.cpp + Settings/AudioPane.cpp Settings/GeneralPane.cpp Settings/InterfacePane.cpp Settings/PathPane.cpp diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp index c6d903c3a6..a930801ebe 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp @@ -11,8 +11,10 @@ #include #include "DolphinQt2/Config/SettingsWindow.h" +#include "DolphinQt2/MainWindow.h" #include "DolphinQt2/Resources.h" #include "DolphinQt2/Settings.h" +#include "DolphinQt2/Settings/AudioPane.h" #include "DolphinQt2/Settings/GeneralPane.h" #include "DolphinQt2/Settings/InterfacePane.h" #include "DolphinQt2/Settings/PathPane.h" @@ -57,6 +59,14 @@ void SettingsWindow::SetupSettingsWidget() // Panes initalised here m_settings_outer->addWidget(new GeneralPane); m_settings_outer->addWidget(new InterfacePane); + + auto* audio_pane = new AudioPane; + connect(this, &SettingsWindow::EmulationStarted, + [audio_pane] { audio_pane->OnEmulationStateChanged(true); }); + connect(this, &SettingsWindow::EmulationStopped, + [audio_pane] { audio_pane->OnEmulationStateChanged(false); }); + m_settings_outer->addWidget(audio_pane); + m_settings_outer->addWidget(new PathPane); } @@ -85,6 +95,7 @@ void SettingsWindow::MakeCategoryList() AddCategoryToList(tr("General"), "config"); AddCategoryToList(tr("Interface"), "browse"); + AddCategoryToList(tr("Audio"), "play"); AddCategoryToList(tr("Paths"), "browse"); connect(m_categories, &QListWidget::currentItemChanged, this, &SettingsWindow::changePage); } diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.h b/Source/Core/DolphinQt2/Config/SettingsWindow.h index c50b741203..1feeec8661 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.h +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.h @@ -8,6 +8,7 @@ #include +class MainWindow; class QGroupBox; class QListWidget; class QListWidgetItem; @@ -18,6 +19,9 @@ class SettingsWindow final : public QDialog Q_OBJECT public: explicit SettingsWindow(QWidget* parent = nullptr); +signals: + void EmulationStarted(); + void EmulationStopped(); public slots: void changePage(QListWidgetItem* current, QListWidgetItem* previous); diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 7b8e1ac9a6..34d79d5228 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -78,6 +78,7 @@ + @@ -90,6 +91,7 @@ + @@ -157,6 +159,7 @@ + diff --git a/Source/Core/DolphinQt2/MainWindow.cpp b/Source/Core/DolphinQt2/MainWindow.cpp index 92a7ec0020..b80a93ee65 100644 --- a/Source/Core/DolphinQt2/MainWindow.cpp +++ b/Source/Core/DolphinQt2/MainWindow.cpp @@ -121,6 +121,11 @@ void MainWindow::CreateComponents() m_settings_window = new SettingsWindow(this); m_hotkey_window = new MappingWindow(this, 0); + connect(this, &MainWindow::EmulationStarted, m_settings_window, + &SettingsWindow::EmulationStarted); + connect(this, &MainWindow::EmulationStopped, m_settings_window, + &SettingsWindow::EmulationStopped); + InstallHotkeyFilter(m_hotkey_window); InstallHotkeyFilter(m_controllers_window); InstallHotkeyFilter(m_settings_window); diff --git a/Source/Core/DolphinQt2/Settings/AudioPane.cpp b/Source/Core/DolphinQt2/Settings/AudioPane.cpp new file mode 100644 index 0000000000..8202450a05 --- /dev/null +++ b/Source/Core/DolphinQt2/Settings/AudioPane.cpp @@ -0,0 +1,244 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Settings/AudioPane.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "AudioCommon/AudioCommon.h" +#include "Core/ConfigManager.h" +#include "DolphinQt2/Config/SettingsWindow.h" +#include "DolphinQt2/Settings.h" + +AudioPane::AudioPane() +{ + CreateWidgets(); + LoadSettings(); + ConnectWidgets(); + + connect(&Settings::Instance(), &Settings::VolumeChanged, this, &AudioPane::OnVolumeChanged); +} + +void AudioPane::CreateWidgets() +{ + auto* dsp_box = new QGroupBox(tr("DSP Emulator Engine")); + auto* dsp_layout = new QVBoxLayout; + + dsp_box->setLayout(dsp_layout); + m_dsp_hle = new QRadioButton(tr("DSP HLE emulation (fast)")); + m_dsp_lle = new QRadioButton(tr("DSP LLE recompiler")); + m_dsp_interpreter = new QRadioButton(tr("DSP LLE interpreter (slow)")); + + dsp_layout->addStretch(1); + dsp_layout->addWidget(m_dsp_hle); + dsp_layout->addWidget(m_dsp_lle); + dsp_layout->addWidget(m_dsp_interpreter); + dsp_layout->addStretch(1); + + auto* volume_box = new QGroupBox(tr("Volume")); + auto* volume_layout = new QVBoxLayout; + m_volume_slider = new QSlider; + m_volume_indicator = new QLabel(); + + volume_box->setLayout(volume_layout); + + m_volume_slider->setMinimum(0); + m_volume_slider->setMaximum(100); + + m_volume_indicator->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + + volume_layout->addWidget(m_volume_slider, 0, Qt::AlignHCenter); + volume_layout->addWidget(m_volume_indicator, 0, Qt::AlignHCenter); + + auto* backend_box = new QGroupBox(tr("Backend Settings")); + auto* backend_layout = new QFormLayout; + backend_box->setLayout(backend_layout); + m_backend_label = new QLabel(tr("Audio Backend:")); + m_backend_combo = new QComboBox(); + m_latency_label = new QLabel(tr("Latency:")); + m_dolby_pro_logic = new QCheckBox(tr("Dolby Pro Logic II decoder")); + m_latency_spin = new QSpinBox(); + + m_latency_spin->setMinimum(0); + m_latency_spin->setMaximum(30); + m_latency_spin->setToolTip(tr("Sets the latency (in ms). Higher values may reduce audio " + "crackling. Certain backends only.")); + + m_dolby_pro_logic->setToolTip( + tr("Enables Dolby Pro Logic II emulation using 5.1 surround. Certain backends only.")); + + backend_layout->addRow(m_backend_label, m_backend_combo); + backend_layout->addRow(m_latency_label, m_latency_spin); + backend_layout->addRow(m_dolby_pro_logic); + + auto* stretching_box = new QGroupBox(tr("Audio Stretching Settings")); + auto* stretching_layout = new QGridLayout; + m_stretching_enable = new QCheckBox(tr("Enable Audio Stretching")); + m_stretching_buffer_slider = new QSlider(Qt::Horizontal); + m_stretching_buffer_indicator = new QLabel(); + m_stretching_buffer_label = new QLabel(tr("Buffer Size:")); + stretching_box->setLayout(stretching_layout); + + m_stretching_buffer_slider->setMinimum(5); + m_stretching_buffer_slider->setMaximum(300); + + m_stretching_enable->setToolTip(tr("Enables stretching of the audio to match emulation speed.")); + m_stretching_buffer_slider->setToolTip(tr("Size of stretch buffer in milliseconds. " + "Values too low may cause audio crackling.")); + + stretching_layout->addWidget(m_stretching_enable, 0, 0, 1, -1); + stretching_layout->addWidget(m_stretching_buffer_label, 1, 0); + stretching_layout->addWidget(m_stretching_buffer_slider, 1, 1); + stretching_layout->addWidget(m_stretching_buffer_indicator, 1, 2); + + m_main_layout = new QGridLayout; + + m_main_layout->setColumnStretch(0, 1); + m_main_layout->addWidget(dsp_box, 0, 0); + m_main_layout->addWidget(volume_box, 0, 1); + m_main_layout->addWidget(backend_box, 1, 0, 1, -1); + m_main_layout->addWidget(stretching_box, 2, 0, 1, -1); + + setLayout(m_main_layout); +} + +void AudioPane::ConnectWidgets() +{ + connect(m_backend_combo, static_cast(&QComboBox::currentIndexChanged), + this, &AudioPane::SaveSettings); + connect(m_volume_slider, &QSlider::valueChanged, this, &AudioPane::SaveSettings); + connect(m_latency_spin, static_cast(&QSpinBox::valueChanged), this, + &AudioPane::SaveSettings); + connect(m_stretching_buffer_slider, &QSlider::valueChanged, this, &AudioPane::SaveSettings); + connect(m_dolby_pro_logic, &QCheckBox::toggled, this, &AudioPane::SaveSettings); + connect(m_stretching_enable, &QCheckBox::toggled, this, &AudioPane::SaveSettings); + connect(m_dsp_hle, &QRadioButton::toggled, this, &AudioPane::SaveSettings); + connect(m_dsp_lle, &QRadioButton::toggled, this, &AudioPane::SaveSettings); + connect(m_dsp_interpreter, &QRadioButton::toggled, this, &AudioPane::SaveSettings); +} + +void AudioPane::LoadSettings() +{ + auto& settings = Settings::Instance(); + + // DSP + if (SConfig::GetInstance().bDSPHLE) + { + m_dsp_hle->setChecked(true); + } + else + { + m_dsp_lle->setChecked(SConfig::GetInstance().m_DSPEnableJIT); + m_dsp_interpreter->setChecked(!SConfig::GetInstance().m_DSPEnableJIT); + } + + // Backend + const auto current = SConfig::GetInstance().sBackend; + for (const auto& backend : AudioCommon::GetSoundBackends()) + { + m_backend_combo->addItem(tr(backend.c_str()), QVariant(QString::fromStdString(backend))); + if (backend == current) + m_backend_combo->setCurrentIndex(m_backend_combo->count() - 1); + } + + OnBackendChanged(); + + // Volume + OnVolumeChanged(settings.GetVolume()); + + // DPL2 + m_dolby_pro_logic->setChecked(SConfig::GetInstance().bDPL2Decoder); + + // Latency + m_latency_spin->setValue(SConfig::GetInstance().iLatency); + + // Stretch + m_stretching_enable->setChecked(SConfig::GetInstance().m_audio_stretch); + m_stretching_buffer_slider->setValue(SConfig::GetInstance().m_audio_stretch_max_latency); + m_stretching_buffer_slider->setEnabled(m_stretching_enable->isChecked()); + m_stretching_buffer_indicator->setText(tr("%1 ms").arg(m_stretching_buffer_slider->value())); +} + +void AudioPane::SaveSettings() +{ + auto& settings = Settings::Instance(); + + // DSP + SConfig::GetInstance().bDSPHLE = m_dsp_hle->isChecked(); + SConfig::GetInstance().m_DSPEnableJIT = m_dsp_lle->isChecked(); + + // Backend + const auto selection = + m_backend_combo->itemData(m_backend_combo->currentIndex()).toString().toStdString(); + auto& backend = SConfig::GetInstance().sBackend; + + if (selection != backend) + { + backend = selection; + OnBackendChanged(); + } + + // Volume + if (m_volume_slider->value() != settings.GetVolume()) + { + settings.SetVolume(m_volume_slider->value()); + OnVolumeChanged(settings.GetVolume()); + } + + // DPL2 + SConfig::GetInstance().bDPL2Decoder = m_dolby_pro_logic->isChecked(); + + // Latency + SConfig::GetInstance().iLatency = m_latency_spin->value(); + + // Stretch + SConfig::GetInstance().m_audio_stretch = m_stretching_enable->isChecked(); + SConfig::GetInstance().m_audio_stretch_max_latency = m_stretching_buffer_slider->value(); + m_stretching_buffer_label->setEnabled(m_stretching_enable->isChecked()); + m_stretching_buffer_slider->setEnabled(m_stretching_enable->isChecked()); + m_stretching_buffer_indicator->setEnabled(m_stretching_enable->isChecked()); + m_stretching_buffer_indicator->setText( + tr("%1 ms").arg(SConfig::GetInstance().m_audio_stretch_max_latency)); + + AudioCommon::UpdateSoundStream(); +} + +void AudioPane::OnBackendChanged() +{ + const auto backend = SConfig::GetInstance().sBackend; + + m_dolby_pro_logic->setEnabled(AudioCommon::SupportsDPL2Decoder(backend)); + m_latency_label->setEnabled(AudioCommon::SupportsLatencyControl(backend)); + m_latency_spin->setEnabled(AudioCommon::SupportsLatencyControl(backend)); + m_volume_slider->setEnabled(AudioCommon::SupportsVolumeChanges(backend)); + m_volume_indicator->setEnabled(AudioCommon::SupportsVolumeChanges(backend)); +} + +void AudioPane::OnEmulationStateChanged(bool running) +{ + m_dsp_hle->setEnabled(!running); + m_dsp_lle->setEnabled(!running); + m_dsp_interpreter->setEnabled(!running); + m_dolby_pro_logic->setEnabled(!running); + m_backend_label->setEnabled(!running); + m_backend_combo->setEnabled(!running); + m_latency_label->setEnabled(!running); + m_latency_spin->setEnabled(!running); +} + +void AudioPane::OnVolumeChanged(int volume) +{ + m_volume_slider->setValue(volume); + m_volume_indicator->setText(tr("%1 %").arg(volume)); +} diff --git a/Source/Core/DolphinQt2/Settings/AudioPane.h b/Source/Core/DolphinQt2/Settings/AudioPane.h new file mode 100644 index 0000000000..68ca4c682d --- /dev/null +++ b/Source/Core/DolphinQt2/Settings/AudioPane.h @@ -0,0 +1,59 @@ +// Copyright 2017 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class QCheckBox; +class QComboBox; +class QLabel; +class QGridLayout; +class QRadioButton; +class QSlider; +class QSpinBox; +class SettingsWindow; + +class AudioPane final : public QWidget +{ + Q_OBJECT +public: + explicit AudioPane(); + + void OnEmulationStateChanged(bool running); + +private: + void CreateWidgets(); + void ConnectWidgets(); + + void LoadSettings(); + void SaveSettings(); + + void OnBackendChanged(); + void OnVolumeChanged(int volume); + + QGridLayout* m_main_layout; + + // DSP Engine + QRadioButton* m_dsp_hle; + QRadioButton* m_dsp_lle; + QRadioButton* m_dsp_interpreter; + + // Volume + QSlider* m_volume_slider; + QLabel* m_volume_indicator; + + // Backend + QLabel* m_backend_label; + QComboBox* m_backend_combo; + QCheckBox* m_dolby_pro_logic; + QLabel* m_latency_label; + QSpinBox* m_latency_spin; + + // Audio Stretching + QCheckBox* m_stretching_enable; + QLabel* m_stretching_buffer_label; + QSlider* m_stretching_buffer_slider; + QLabel* m_stretching_buffer_indicator; +};