mirror of https://github.com/PCSX2/pcsx2.git
Qt: Fix per-game settings with sliders
This commit is contained in:
parent
336ef58f61
commit
b3bf3e46be
|
@ -20,11 +20,13 @@
|
||||||
|
|
||||||
#include <QtCore/QtCore>
|
#include <QtCore/QtCore>
|
||||||
#include <QtGui/QAction>
|
#include <QtGui/QAction>
|
||||||
|
#include <QtGui/QFont>
|
||||||
#include <QtWidgets/QAbstractButton>
|
#include <QtWidgets/QAbstractButton>
|
||||||
#include <QtWidgets/QCheckBox>
|
#include <QtWidgets/QCheckBox>
|
||||||
#include <QtWidgets/QComboBox>
|
#include <QtWidgets/QComboBox>
|
||||||
#include <QtWidgets/QDoubleSpinBox>
|
#include <QtWidgets/QDoubleSpinBox>
|
||||||
#include <QtWidgets/QFileDialog>
|
#include <QtWidgets/QFileDialog>
|
||||||
|
#include <QtWidgets/QLabel>
|
||||||
#include <QtWidgets/QLineEdit>
|
#include <QtWidgets/QLineEdit>
|
||||||
#include <QtWidgets/QMenu>
|
#include <QtWidgets/QMenu>
|
||||||
#include <QtWidgets/QSlider>
|
#include <QtWidgets/QSlider>
|
||||||
|
@ -101,7 +103,10 @@ namespace SettingWidgetBinder
|
||||||
static void setStringValue(QLineEdit* widget, const QString& value) { widget->setText(value); }
|
static void setStringValue(QLineEdit* widget, const QString& value) { widget->setText(value); }
|
||||||
static void makeNullableString(QLineEdit* widget, const QString& globalValue) { widget->setEnabled(false); }
|
static void makeNullableString(QLineEdit* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||||
static std::optional<QString> getNullableStringValue(const QLineEdit* widget) { return getStringValue(widget); }
|
static std::optional<QString> getNullableStringValue(const QLineEdit* widget) { return getStringValue(widget); }
|
||||||
static void setNullableStringValue(QLineEdit* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
static void setNullableStringValue(QLineEdit* widget, std::optional<QString> value)
|
||||||
|
{
|
||||||
|
setStringValue(widget, value.value_or(QString()));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static void connectValueChanged(QLineEdit* widget, F func)
|
static void connectValueChanged(QLineEdit* widget, F func)
|
||||||
|
@ -120,15 +125,16 @@ namespace SettingWidgetBinder
|
||||||
static void makeNullableBool(QComboBox* widget, bool globalValue)
|
static void makeNullableBool(QComboBox* widget, bool globalValue)
|
||||||
{
|
{
|
||||||
widget->insertItem(0, globalValue ? qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") :
|
widget->insertItem(0, globalValue ? qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") :
|
||||||
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]"));
|
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getIntValue(const QComboBox* widget) { return widget->currentIndex(); }
|
static int getIntValue(const QComboBox* widget) { return widget->currentIndex(); }
|
||||||
static void setIntValue(QComboBox* widget, int value) { widget->setCurrentIndex(value); }
|
static void setIntValue(QComboBox* widget, int value) { widget->setCurrentIndex(value); }
|
||||||
static void makeNullableInt(QComboBox* widget, int globalValue)
|
static void makeNullableInt(QComboBox* widget, int globalValue)
|
||||||
{
|
{
|
||||||
widget->insertItem(0, qApp->translate("SettingsDialog", "Use Global Setting [%1]")
|
widget->insertItem(
|
||||||
.arg((globalValue >= 0 && globalValue < widget->count()) ? widget->itemText(globalValue) : QString()));
|
0, qApp->translate("SettingsDialog", "Use Global Setting [%1]")
|
||||||
|
.arg((globalValue >= 0 && globalValue < widget->count()) ? widget->itemText(globalValue) : QString()));
|
||||||
}
|
}
|
||||||
static std::optional<int> getNullableIntValue(const QComboBox* widget)
|
static std::optional<int> getNullableIntValue(const QComboBox* widget)
|
||||||
{
|
{
|
||||||
|
@ -143,10 +149,10 @@ namespace SettingWidgetBinder
|
||||||
static void setFloatValue(QComboBox* widget, float value) { widget->setCurrentIndex(static_cast<int>(value)); }
|
static void setFloatValue(QComboBox* widget, float value) { widget->setCurrentIndex(static_cast<int>(value)); }
|
||||||
static void makeNullableFloat(QComboBox* widget, float globalValue)
|
static void makeNullableFloat(QComboBox* widget, float globalValue)
|
||||||
{
|
{
|
||||||
widget->insertItem(0,
|
widget->insertItem(0, qApp->translate("SettingsDialog", "Use Global Setting [%1]")
|
||||||
qApp->translate("SettingsDialog", "Use Global Setting [%1]")
|
.arg((globalValue >= 0.0f && static_cast<int>(globalValue) < widget->count()) ?
|
||||||
.arg((globalValue >= 0.0f && static_cast<int>(globalValue) < widget->count()) ? widget->itemText(static_cast<int>(globalValue)) :
|
widget->itemText(static_cast<int>(globalValue)) :
|
||||||
QString()));
|
QString()));
|
||||||
}
|
}
|
||||||
static std::optional<float> getNullableFloatValue(const QComboBox* widget)
|
static std::optional<float> getNullableFloatValue(const QComboBox* widget)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +182,10 @@ namespace SettingWidgetBinder
|
||||||
|
|
||||||
widget->setCurrentText(value);
|
widget->setCurrentText(value);
|
||||||
}
|
}
|
||||||
static void makeNullableString(QComboBox* widget, const QString& globalValue) { makeNullableInt(widget, widget->findData(globalValue)); }
|
static void makeNullableString(QComboBox* widget, const QString& globalValue)
|
||||||
|
{
|
||||||
|
makeNullableInt(widget, widget->findData(globalValue));
|
||||||
|
}
|
||||||
static std::optional<QString> getNullableStringValue(const QComboBox* widget)
|
static std::optional<QString> getNullableStringValue(const QComboBox* widget)
|
||||||
{
|
{
|
||||||
return isNullValue(widget) ? std::nullopt : std::optional<QString>(getStringValue(widget));
|
return isNullValue(widget) ? std::nullopt : std::optional<QString>(getStringValue(widget));
|
||||||
|
@ -239,7 +248,7 @@ namespace SettingWidgetBinder
|
||||||
{
|
{
|
||||||
return (widget->checkState() == Qt::PartiallyChecked) ?
|
return (widget->checkState() == Qt::PartiallyChecked) ?
|
||||||
std::nullopt :
|
std::nullopt :
|
||||||
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
|
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
|
||||||
}
|
}
|
||||||
static void setNullableStringValue(QCheckBox* widget, std::optional<QString> value)
|
static void setNullableStringValue(QCheckBox* widget, std::optional<QString> value)
|
||||||
{
|
{
|
||||||
|
@ -278,7 +287,10 @@ namespace SettingWidgetBinder
|
||||||
static void setStringValue(QSlider* widget, const QString& value) { widget->setValue(value.toInt()); }
|
static void setStringValue(QSlider* widget, const QString& value) { widget->setValue(value.toInt()); }
|
||||||
static void makeNullableString(QSlider* widget, const QString& globalValue) { widget->setEnabled(false); }
|
static void makeNullableString(QSlider* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||||
static std::optional<QString> getNullableStringValue(const QSlider* widget) { return getStringValue(widget); }
|
static std::optional<QString> getNullableStringValue(const QSlider* widget) { return getStringValue(widget); }
|
||||||
static void setNullableStringValue(QSlider* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
static void setNullableStringValue(QSlider* widget, std::optional<QString> value)
|
||||||
|
{
|
||||||
|
setStringValue(widget, value.value_or(QString()));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static void connectValueChanged(QSlider* widget, F func)
|
static void connectValueChanged(QSlider* widget, F func)
|
||||||
|
@ -568,7 +580,10 @@ namespace SettingWidgetBinder
|
||||||
static void setStringValue(QAction* widget, const QString& value) { widget->setChecked(value.toInt() != 0); }
|
static void setStringValue(QAction* widget, const QString& value) { widget->setChecked(value.toInt() != 0); }
|
||||||
static void makeNullableString(QAction* widget, const QString& globalValue) { widget->setEnabled(false); }
|
static void makeNullableString(QAction* widget, const QString& globalValue) { widget->setEnabled(false); }
|
||||||
static std::optional<QString> getNullableStringValue(const QAction* widget) { return getStringValue(widget); }
|
static std::optional<QString> getNullableStringValue(const QAction* widget) { return getStringValue(widget); }
|
||||||
static void setNullableStringValue(QAction* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
|
static void setNullableStringValue(QAction* widget, std::optional<QString> value)
|
||||||
|
{
|
||||||
|
setStringValue(widget, value.value_or(QString()));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
static void connectValueChanged(QAction* widget, F func)
|
static void connectValueChanged(QAction* widget, F func)
|
||||||
|
@ -580,7 +595,8 @@ namespace SettingWidgetBinder
|
||||||
/// Binds a widget's value to a setting, updating it when the value changes.
|
/// Binds a widget's value to a setting, updating it when the value changes.
|
||||||
|
|
||||||
template <typename WidgetType>
|
template <typename WidgetType>
|
||||||
static void BindWidgetToBoolSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, bool default_value)
|
static void BindWidgetToBoolSetting(
|
||||||
|
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, bool default_value)
|
||||||
{
|
{
|
||||||
using Accessor = SettingAccessor<WidgetType>;
|
using Accessor = SettingAccessor<WidgetType>;
|
||||||
|
|
||||||
|
@ -661,7 +677,8 @@ namespace SettingWidgetBinder
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WidgetType>
|
template <typename WidgetType>
|
||||||
static void BindWidgetToFloatSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, float default_value)
|
static void BindWidgetToFloatSetting(
|
||||||
|
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, float default_value)
|
||||||
{
|
{
|
||||||
using Accessor = SettingAccessor<WidgetType>;
|
using Accessor = SettingAccessor<WidgetType>;
|
||||||
|
|
||||||
|
@ -788,7 +805,8 @@ namespace SettingWidgetBinder
|
||||||
|
|
||||||
template <typename WidgetType, typename DataType>
|
template <typename WidgetType, typename DataType>
|
||||||
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
|
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
|
||||||
std::optional<DataType> (*from_string_function)(const char* str), const char* (*to_string_function)(DataType value), DataType default_value)
|
std::optional<DataType> (*from_string_function)(const char* str), const char* (*to_string_function)(DataType value),
|
||||||
|
DataType default_value)
|
||||||
{
|
{
|
||||||
using Accessor = SettingAccessor<WidgetType>;
|
using Accessor = SettingAccessor<WidgetType>;
|
||||||
using UnderlyingType = std::underlying_type_t<DataType>;
|
using UnderlyingType = std::underlying_type_t<DataType>;
|
||||||
|
@ -798,7 +816,8 @@ namespace SettingWidgetBinder
|
||||||
|
|
||||||
if (sif)
|
if (sif)
|
||||||
{
|
{
|
||||||
Accessor::makeNullableInt(widget, typed_value.has_value() ? static_cast<int>(static_cast<UnderlyingType>(typed_value.value())) : 0);
|
Accessor::makeNullableInt(
|
||||||
|
widget, typed_value.has_value() ? static_cast<int>(static_cast<UnderlyingType>(typed_value.value())) : 0);
|
||||||
|
|
||||||
std::string sif_value;
|
std::string sif_value;
|
||||||
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
|
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
|
||||||
|
@ -909,8 +928,8 @@ namespace SettingWidgetBinder
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WidgetType>
|
template <typename WidgetType>
|
||||||
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, const char** enum_names,
|
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
|
||||||
const char** enum_values, const char* default_value)
|
const char** enum_names, const char** enum_values, const char* default_value)
|
||||||
{
|
{
|
||||||
using Accessor = SettingAccessor<WidgetType>;
|
using Accessor = SettingAccessor<WidgetType>;
|
||||||
|
|
||||||
|
@ -973,8 +992,9 @@ namespace SettingWidgetBinder
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename WidgetType>
|
template <typename WidgetType>
|
||||||
static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget, QAbstractButton* browse_button, QAbstractButton* open_button,
|
static void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget, QAbstractButton* browse_button,
|
||||||
QAbstractButton* reset_button, std::string section, std::string key, std::string default_value, bool use_relative = true)
|
QAbstractButton* open_button, QAbstractButton* reset_button, std::string section, std::string key, std::string default_value,
|
||||||
|
bool use_relative = true)
|
||||||
{
|
{
|
||||||
using Accessor = SettingAccessor<WidgetType>;
|
using Accessor = SettingAccessor<WidgetType>;
|
||||||
|
|
||||||
|
@ -1042,8 +1062,76 @@ namespace SettingWidgetBinder
|
||||||
}
|
}
|
||||||
if (reset_button)
|
if (reset_button)
|
||||||
{
|
{
|
||||||
QObject::connect(reset_button, &QAbstractButton::clicked, reset_button,
|
QObject::connect(reset_button, &QAbstractButton::clicked, reset_button, [widget, default_value = std::move(default_value)]() {
|
||||||
[widget, default_value = std::move(default_value)]() { Accessor::setStringValue(widget, QString::fromStdString(default_value)); });
|
Accessor::setStringValue(widget, QString::fromStdString(default_value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BindSliderToIntSetting(SettingsInterface* sif, QSlider* slider, QLabel* label, const QString& label_suffix,
|
||||||
|
std::string section, std::string key, s32 default_value)
|
||||||
|
{
|
||||||
|
const s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
|
||||||
|
|
||||||
|
if (sif)
|
||||||
|
{
|
||||||
|
const QFont orig_font(label->font());
|
||||||
|
QFont bold_font(orig_font);
|
||||||
|
bold_font.setBold(true);
|
||||||
|
|
||||||
|
const s32 current_value = sif->GetOptionalIntValue(section.c_str(), key.c_str()).value_or(global_value);
|
||||||
|
slider->setValue(current_value);
|
||||||
|
|
||||||
|
label->setText(QStringLiteral("%1%2").arg(current_value).arg(label_suffix));
|
||||||
|
if (current_value == global_value)
|
||||||
|
label->setFont(orig_font);
|
||||||
|
else
|
||||||
|
label->setFont(bold_font);
|
||||||
|
|
||||||
|
slider->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
slider->connect(slider, &QSpinBox::customContextMenuRequested, slider,
|
||||||
|
[sif, slider, label, label_suffix, orig_font = std::move(orig_font), section, key, default_value](const QPoint& pt) {
|
||||||
|
QMenu menu(slider);
|
||||||
|
slider->connect(menu.addAction(qApp->translate("SettingWidgetBinder", "Reset")), &QAction::triggered, slider,
|
||||||
|
[sif, slider, label, label_suffix, orig_font, section, key, default_value]() {
|
||||||
|
const s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
|
||||||
|
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
|
||||||
|
label->setFont(orig_font);
|
||||||
|
|
||||||
|
if (sif->ContainsValue(section.c_str(), key.c_str()))
|
||||||
|
{
|
||||||
|
sif->DeleteValue(section.c_str(), key.c_str());
|
||||||
|
sif->Save();
|
||||||
|
g_emu_thread->reloadGameSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.exec(slider->mapToGlobal(pt));
|
||||||
|
});
|
||||||
|
|
||||||
|
slider->connect(slider, &QSlider::valueChanged, slider,
|
||||||
|
[sif, label, label_suffix, section = std::move(section), key = std::move(key), default_value,
|
||||||
|
orig_font = std::move(orig_font), bold_font = std::move(bold_font)](int value) {
|
||||||
|
label->setText(QStringLiteral("%1%2").arg(value).arg(label_suffix));
|
||||||
|
|
||||||
|
if (label->font() != bold_font)
|
||||||
|
label->setFont(bold_font);
|
||||||
|
sif->SetIntValue(section.c_str(), key.c_str(), value);
|
||||||
|
sif->Save();
|
||||||
|
g_emu_thread->reloadGameSettings();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slider->setValue(global_value);
|
||||||
|
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
|
||||||
|
|
||||||
|
slider->connect(slider, &QSlider::valueChanged, slider,
|
||||||
|
[sif, label, label_suffix, section = std::move(section), key = std::move(key), default_value](int value) {
|
||||||
|
label->setText(QStringLiteral("%1%2").arg(value).arg(label_suffix));
|
||||||
|
Host::SetBaseIntSettingValue(section.c_str(), key.c_str(), value);
|
||||||
|
Host::CommitBaseSettingChanges();
|
||||||
|
g_emu_thread->applySettings();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace SettingWidgetBinder
|
} // namespace SettingWidgetBinder
|
||||||
|
|
|
@ -71,8 +71,10 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
|
||||||
|
|
||||||
SettingWidgetBinder::BindWidgetToEnumSetting(
|
SettingWidgetBinder::BindWidgetToEnumSetting(
|
||||||
sif, m_ui.outputModule, "SPU2/Output", "OutputModule", s_output_module_entries, s_output_module_values, DEFAULT_OUTPUT_MODULE);
|
sif, m_ui.outputModule, "SPU2/Output", "OutputModule", s_output_module_entries, s_output_module_values, DEFAULT_OUTPUT_MODULE);
|
||||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.targetLatency, "SPU2/Output", "Latency", DEFAULT_TARGET_LATENCY);
|
SettingWidgetBinder::BindSliderToIntSetting(
|
||||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.outputLatency, "SPU2/Output", "OutputLatency", DEFAULT_OUTPUT_LATENCY);
|
sif, m_ui.targetLatency, m_ui.targetLatencyLabel, tr(" ms"), "SPU2/Output", "Latency", DEFAULT_TARGET_LATENCY);
|
||||||
|
SettingWidgetBinder::BindSliderToIntSetting(
|
||||||
|
sif, m_ui.outputLatency, m_ui.outputLatencyLabel, tr(" ms"), "SPU2/Output", "OutputLatency", DEFAULT_OUTPUT_LATENCY);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.outputLatencyMinimal, "SPU2/Output", "OutputLatencyMinimal", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.outputLatencyMinimal, "SPU2/Output", "OutputLatencyMinimal", false);
|
||||||
connect(m_ui.outputModule, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::outputModuleChanged);
|
connect(m_ui.outputModule, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::outputModuleChanged);
|
||||||
connect(m_ui.backend, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::outputBackendChanged);
|
connect(m_ui.backend, &QComboBox::currentIndexChanged, this, &AudioSettingsWidget::outputBackendChanged);
|
||||||
|
@ -83,26 +85,30 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
|
||||||
outputModuleChanged();
|
outputModuleChanged();
|
||||||
|
|
||||||
m_ui.volume->setValue(m_dialog->getEffectiveIntValue("SPU2/Mixing", "FinalVolume", DEFAULT_VOLUME));
|
m_ui.volume->setValue(m_dialog->getEffectiveIntValue("SPU2/Mixing", "FinalVolume", DEFAULT_VOLUME));
|
||||||
|
m_ui.volume->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(m_ui.volume, &QSlider::valueChanged, this, &AudioSettingsWidget::volumeChanged);
|
connect(m_ui.volume, &QSlider::valueChanged, this, &AudioSettingsWidget::volumeChanged);
|
||||||
|
connect(m_ui.volume, &QSlider::customContextMenuRequested, this, &AudioSettingsWidget::volumeContextMenuRequested);
|
||||||
|
updateVolumeLabel();
|
||||||
|
if (sif && sif->ContainsValue("SPU2/Mixing", "FinalVolume"))
|
||||||
|
{
|
||||||
|
QFont bold_font(m_ui.volume->font());
|
||||||
|
bold_font.setBold(true);
|
||||||
|
m_ui.volumeLabel->setFont(bold_font);
|
||||||
|
}
|
||||||
|
|
||||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
SettingWidgetBinder::BindSliderToIntSetting(sif, m_ui.sequenceLength, m_ui.sequenceLengthLabel, tr(" ms"), "Soundtouch",
|
||||||
sif, m_ui.sequenceLength, "Soundtouch", "SequenceLengthMS", DEFAULT_SOUNDTOUCH_SEQUENCE_LENGTH);
|
"SequenceLengthMS", DEFAULT_SOUNDTOUCH_SEQUENCE_LENGTH);
|
||||||
connect(m_ui.sequenceLength, &QSlider::valueChanged, this, &AudioSettingsWidget::updateTimestretchSequenceLengthLabel);
|
SettingWidgetBinder::BindSliderToIntSetting(
|
||||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.seekWindowSize, "Soundtouch", "SeekWindowMS", DEFAULT_SOUNDTOUCH_SEEK_WINDOW);
|
sif, m_ui.seekWindowSize, m_ui.seekWindowSizeLabel, tr(" ms"), "Soundtouch", "SeekWindowMS", DEFAULT_SOUNDTOUCH_SEEK_WINDOW);
|
||||||
connect(m_ui.seekWindowSize, &QSlider::valueChanged, this, &AudioSettingsWidget::updateTimestretchSeekwindowLengthLabel);
|
SettingWidgetBinder::BindSliderToIntSetting(
|
||||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.overlap, "Soundtouch", "OverlapMS", DEFAULT_SOUNDTOUCH_OVERLAP);
|
sif, m_ui.overlap, m_ui.overlapLabel, tr(" ms"), "Soundtouch", "OverlapMS", DEFAULT_SOUNDTOUCH_OVERLAP);
|
||||||
connect(m_ui.overlap, &QSlider::valueChanged, this, &AudioSettingsWidget::updateTimestretchOverlapLabel);
|
|
||||||
connect(m_ui.resetTimestretchDefaults, &QPushButton::clicked, this, &AudioSettingsWidget::resetTimestretchDefaults);
|
connect(m_ui.resetTimestretchDefaults, &QPushButton::clicked, this, &AudioSettingsWidget::resetTimestretchDefaults);
|
||||||
|
|
||||||
m_ui.label_3b->setVisible(false);
|
m_ui.label_3b->setVisible(false);
|
||||||
m_ui.dplLevel->setVisible(false);
|
m_ui.dplLevel->setVisible(false);
|
||||||
|
|
||||||
volumeChanged(m_ui.volume->value());
|
|
||||||
onMinimalOutputLatencyStateChanged();
|
onMinimalOutputLatencyStateChanged();
|
||||||
updateLatencyLabels();
|
updateLatencyLabels();
|
||||||
updateTimestretchSequenceLengthLabel();
|
|
||||||
updateTimestretchSeekwindowLengthLabel();
|
|
||||||
updateTimestretchOverlapLabel();
|
|
||||||
|
|
||||||
dialog->registerWidgetHelp(m_ui.interpolation, tr("Interpolation"), tr("Gaussian (PS2-like / great sound)"), tr(""));
|
dialog->registerWidgetHelp(m_ui.interpolation, tr("Interpolation"), tr("Gaussian (PS2-like / great sound)"), tr(""));
|
||||||
|
|
||||||
|
@ -127,7 +133,8 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
|
||||||
|
|
||||||
dialog->registerWidgetHelp(m_ui.overlap, tr("Overlap"), tr("10 ms"), tr(""));
|
dialog->registerWidgetHelp(m_ui.overlap, tr("Overlap"), tr("10 ms"), tr(""));
|
||||||
|
|
||||||
dialog->registerWidgetHelp(m_ui.volume, tr("Volume"), tr("100%"), tr(""));
|
dialog->registerWidgetHelp(m_ui.volume, tr("Volume"), tr("100%"),
|
||||||
|
tr("Pre-applies a volume modifier to the game's audio output before forwarding it to your computer."));
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioSettingsWidget::~AudioSettingsWidget() = default;
|
AudioSettingsWidget::~AudioSettingsWidget() = default;
|
||||||
|
@ -229,11 +236,16 @@ void AudioSettingsWidget::updateDevices()
|
||||||
|
|
||||||
void AudioSettingsWidget::volumeChanged(int value)
|
void AudioSettingsWidget::volumeChanged(int value)
|
||||||
{
|
{
|
||||||
m_ui.volumeLabel->setText(tr("%1%").arg(value, 3));
|
|
||||||
|
|
||||||
// Nasty, but needed so we don't do a full settings apply and lag while dragging.
|
// Nasty, but needed so we don't do a full settings apply and lag while dragging.
|
||||||
if (SettingsInterface* sif = m_dialog->getSettingsInterface())
|
if (SettingsInterface* sif = m_dialog->getSettingsInterface())
|
||||||
{
|
{
|
||||||
|
if (!m_ui.volumeLabel->font().bold())
|
||||||
|
{
|
||||||
|
QFont bold_font(m_ui.volumeLabel->font());
|
||||||
|
bold_font.setBold(true);
|
||||||
|
m_ui.volumeLabel->setFont(bold_font);
|
||||||
|
}
|
||||||
|
|
||||||
sif->SetIntValue("SPU2/Mixing", "FinalVolume", value);
|
sif->SetIntValue("SPU2/Mixing", "FinalVolume", value);
|
||||||
sif->Save();
|
sif->Save();
|
||||||
}
|
}
|
||||||
|
@ -254,6 +266,42 @@ void AudioSettingsWidget::volumeChanged(int value)
|
||||||
SPU2::SetOutputVolume(value);
|
SPU2::SetOutputVolume(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateVolumeLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSettingsWidget::volumeContextMenuRequested(const QPoint& pt)
|
||||||
|
{
|
||||||
|
QMenu menu(m_ui.volume);
|
||||||
|
m_ui.volume->connect(menu.addAction(qApp->translate("SettingWidgetBinder", "Reset")), &QAction::triggered, this, [this]() {
|
||||||
|
const s32 global_value = Host::GetBaseIntSettingValue("SPU2/Mixing", "FinalVolume", DEFAULT_VOLUME);
|
||||||
|
{
|
||||||
|
QSignalBlocker sb(m_ui.volumeLabel);
|
||||||
|
m_ui.volume->setValue(global_value);
|
||||||
|
updateVolumeLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ui.volumeLabel->font().bold())
|
||||||
|
{
|
||||||
|
QFont orig_font(m_ui.volumeLabel->font());
|
||||||
|
orig_font.setBold(false);
|
||||||
|
m_ui.volumeLabel->setFont(orig_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||||
|
if (sif->ContainsValue("SPU2/Mixing", "FinalVolume"))
|
||||||
|
{
|
||||||
|
sif->DeleteValue("SPU2/Mixing", "FinalVolume");
|
||||||
|
sif->Save();
|
||||||
|
g_emu_thread->reloadGameSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.exec(m_ui.volume->mapToGlobal(pt));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioSettingsWidget::updateVolumeLabel()
|
||||||
|
{
|
||||||
|
m_ui.volumeLabel->setText(tr("%1%").arg(m_ui.volume->value()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSettingsWidget::updateTargetLatencyRange()
|
void AudioSettingsWidget::updateTargetLatencyRange()
|
||||||
|
@ -271,7 +319,6 @@ void AudioSettingsWidget::updateLatencyLabels()
|
||||||
{
|
{
|
||||||
const bool minimal_output = m_dialog->getEffectiveBoolValue("SPU2/Output", "OutputLatencyMinimal", false);
|
const bool minimal_output = m_dialog->getEffectiveBoolValue("SPU2/Output", "OutputLatencyMinimal", false);
|
||||||
|
|
||||||
m_ui.targetLatencyLabel->setText(tr("%1 ms").arg(m_ui.targetLatency->value()));
|
|
||||||
m_ui.outputLatencyLabel->setText(minimal_output ? tr("N/A") : tr("%1 ms").arg(m_ui.outputLatency->value()));
|
m_ui.outputLatencyLabel->setText(minimal_output ? tr("N/A") : tr("%1 ms").arg(m_ui.outputLatency->value()));
|
||||||
|
|
||||||
const u32 output_latency_ms =
|
const u32 output_latency_ms =
|
||||||
|
@ -295,21 +342,6 @@ void AudioSettingsWidget::onMinimalOutputLatencyStateChanged()
|
||||||
m_ui.outputLatency->setEnabled(!m_dialog->getEffectiveBoolValue("SPU2/Output", "OutputLatencyMinimal", false));
|
m_ui.outputLatency->setEnabled(!m_dialog->getEffectiveBoolValue("SPU2/Output", "OutputLatencyMinimal", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioSettingsWidget::updateTimestretchSequenceLengthLabel()
|
|
||||||
{
|
|
||||||
m_ui.sequenceLengthLabel->setText(tr("%1 ms").arg(m_ui.sequenceLength->value()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioSettingsWidget::updateTimestretchSeekwindowLengthLabel()
|
|
||||||
{
|
|
||||||
m_ui.seekWindowSizeLabel->setText(tr("%1 ms").arg(m_ui.seekWindowSize->value()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioSettingsWidget::updateTimestretchOverlapLabel()
|
|
||||||
{
|
|
||||||
m_ui.overlapLabel->setText(tr("%1 ms").arg(m_ui.overlap->value()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioSettingsWidget::resetTimestretchDefaults()
|
void AudioSettingsWidget::resetTimestretchDefaults()
|
||||||
{
|
{
|
||||||
m_ui.sequenceLength->setValue(DEFAULT_SOUNDTOUCH_SEQUENCE_LENGTH);
|
m_ui.sequenceLength->setValue(DEFAULT_SOUNDTOUCH_SEQUENCE_LENGTH);
|
||||||
|
|
|
@ -35,15 +35,15 @@ private Q_SLOTS:
|
||||||
void outputBackendChanged();
|
void outputBackendChanged();
|
||||||
void updateDevices();
|
void updateDevices();
|
||||||
void volumeChanged(int value);
|
void volumeChanged(int value);
|
||||||
|
void volumeContextMenuRequested(const QPoint& pt);
|
||||||
void updateTargetLatencyRange();
|
void updateTargetLatencyRange();
|
||||||
void updateLatencyLabels();
|
void updateLatencyLabels();
|
||||||
void onMinimalOutputLatencyStateChanged();
|
void onMinimalOutputLatencyStateChanged();
|
||||||
void updateTimestretchSequenceLengthLabel();
|
|
||||||
void updateTimestretchSeekwindowLengthLabel();
|
|
||||||
void updateTimestretchOverlapLabel();
|
|
||||||
void resetTimestretchDefaults();
|
void resetTimestretchDefaults();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateVolumeLabel();
|
||||||
|
|
||||||
SettingsDialog* m_dialog;
|
SettingsDialog* m_dialog;
|
||||||
Ui::AudioSettingsWidget m_ui;
|
Ui::AudioSettingsWidget m_ui;
|
||||||
u32 m_output_device_latency = 0;
|
u32 m_output_device_latency = 0;
|
||||||
|
|
Loading…
Reference in New Issue