Qt: Add volume reset button

This commit is contained in:
Stenzek 2024-04-25 13:21:12 +10:00
parent 7548113afd
commit 5e9a47f82b
No known key found for this signature in database
6 changed files with 118 additions and 36 deletions

View file

@ -4821,10 +4821,10 @@ void FullscreenUI::DrawAudioSettingsPage()
DrawIntRangeSetting(bsi, FSUI_CSTR("Output Volume"),
FSUI_CSTR("Controls the volume of the audio played on the host."), "Audio", "OutputVolume", 100,
0, 100, "%d%%");
0, 200, "%d%%");
DrawIntRangeSetting(bsi, FSUI_CSTR("Fast Forward Volume"),
FSUI_CSTR("Controls the volume of the audio played on the host when fast forwarding."), "Audio",
"FastForwardVolume", 100, 0, 100, "%d%%");
"FastForwardVolume", 200, 0, 100, "%d%%");
DrawToggleSetting(bsi, FSUI_CSTR("Mute All Sound"),
FSUI_CSTR("Prevents the emulator from producing any audible sound."), "Audio", "OutputMuted",
false);

View file

@ -518,7 +518,7 @@ DEFINE_HOTKEY("AudioVolumeUp", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOO
{
g_settings.audio_output_muted = false;
const s32 volume = std::min<s32>(System::GetAudioOutputVolume() + 10, 100);
const s32 volume = std::min<s32>(System::GetAudioOutputVolume() + 10, 200);
g_settings.audio_output_volume = volume;
g_settings.audio_fast_forward_volume = volume;
SPU::GetOutputStream()->SetOutputVolume(volume);

View file

@ -84,6 +84,8 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* dialog, QWidget* parent
tr("%"), "Audio", "FastForwardVolume", 100);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.muted, "Audio", "OutputMuted", false);
}
connect(m_ui.resetVolume, &QToolButton::clicked, this, [this]() { resetVolume(false); });
connect(m_ui.resetFastForwardVolume, &QToolButton::clicked, this, [this]() { resetVolume(true); });
dialog->registerWidgetHelp(
m_ui.audioBackend, tr("Audio Backend"), QStringLiteral("Cubeb"),
@ -117,6 +119,12 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsWindow* dialog, QWidget* parent
dialog->registerWidgetHelp(m_ui.stretchSettings, tr("Stretch Settings"), tr("N/A"),
tr("These settings fine-tune the behavior of the SoundTouch audio time stretcher when "
"running outside of 100% speed."));
dialog->registerWidgetHelp(m_ui.resetVolume, tr("Reset Volume"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets volume back to the global/inherited setting.") :
tr("Resets volume back to the default, i.e. full."));
dialog->registerWidgetHelp(m_ui.resetFastForwardVolume, tr("Reset Fast Forward Volume"), tr("N/A"),
m_dialog->isPerGameSettings() ? tr("Resets volume back to the global/inherited setting.") :
tr("Resets volume back to the default, i.e. full."));
}
AudioSettingsWidget::~AudioSettingsWidget() = default;
@ -478,4 +486,30 @@ void AudioSettingsWidget::onStretchSettingsClicked()
});
dlg.exec();
}
}
void AudioSettingsWidget::resetVolume(bool fast_forward)
{
const char* key = fast_forward ? "FastForwardVolume" : "OutputVolume";
QSlider* const slider = fast_forward ? m_ui.fastForwardVolume : m_ui.volume;
QLabel* const label = fast_forward ? m_ui.fastForwardVolumeLabel : m_ui.volumeLabel;
if (m_dialog->isPerGameSettings())
{
m_dialog->removeSettingValue("Audio", key);
const int value = m_dialog->getEffectiveIntValue("Audio", key, 100);
QSignalBlocker sb(slider);
slider->setValue(value);
label->setText(QStringLiteral("%1%2").arg(value).arg(tr("%")));
// remove bold font if it was previously overridden
QFont font(label->font());
font.setBold(false);
label->setFont(font);
}
else
{
slider->setValue(100);
}
}

View file

@ -42,6 +42,7 @@ private:
AudioBackend getEffectiveBackend() const;
AudioExpansionMode getEffectiveExpansionMode() const;
u32 getEffectiveExpansionBlockSize() const;
void resetVolume(bool fast_forward);
Ui::AudioSettingsWidget m_ui;
SettingsWindow* m_dialog;

View file

@ -246,6 +246,16 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="resetVolume">
<property name="toolTip">
<string>Stretch Settings</string>
</property>
<property name="icon">
<iconset theme="refresh-line"/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
@ -285,6 +295,16 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="resetFastForwardVolume">
<property name="toolTip">
<string>Stretch Settings</string>
</property>
<property name="icon">
<iconset theme="refresh-line"/>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">

View file

@ -34,7 +34,6 @@ namespace SettingWidgetBinder {
static constexpr const char* NULLABLE_PROPERTY = "SettingWidgetBinder_isNullable";
static constexpr const char* IS_NULL_PROPERTY = "SettingWidgetBinder_isNull";
static constexpr const char* GLOBAL_VALUE_PROPERTY = "SettingWidgetBinder_globalValue";
static constexpr const char* IS_UPDATING_PROPERTY = "SettingWidgetBinder_isUpdating";
template<typename T>
struct SettingAccessor
@ -351,39 +350,25 @@ struct SettingAccessor<QSlider>
template<typename F>
static void connectValueChanged(QSlider* widget, F func)
{
if (!isNullable(widget) || widget->contextMenuPolicy() == Qt::CustomContextMenu)
if (!isNullable(widget))
{
widget->connect(widget, &QSlider::valueChanged, func);
}
else
{
// How much do I hate this? A _lot_. We need to be able to run handlers (e.g. for labels), which get connected to
// valueChanged() above, but the user changing the control also triggers valueChanged()... so catch the recursion.
widget->setProperty(IS_UPDATING_PROPERTY, QVariant(false));
widget->setContextMenuPolicy(Qt::CustomContextMenu);
widget->connect(widget, &QSlider::customContextMenuRequested, widget, [widget, func](const QPoint& pt) {
QMenu menu(widget);
widget->connect(menu.addAction(qApp->translate("SettingWidgetBinder", "Reset")), &QAction::triggered, widget,
[widget, func = std::move(func)]() {
if (widget->property(IS_UPDATING_PROPERTY).toBool())
return;
const bool old = widget->blockSignals(true);
setNullableIntValue(widget, std::nullopt);
widget->blockSignals(old);
func();
widget->setProperty(IS_UPDATING_PROPERTY, QVariant(true));
emit widget->valueChanged(widget->value());
widget->setProperty(IS_UPDATING_PROPERTY, QVariant(false));
});
menu.exec(widget->mapToGlobal(pt));
});
widget->connect(widget, &QSlider::valueChanged, widget, [widget, func = std::move(func)]() {
if (widget->property(IS_UPDATING_PROPERTY).toBool())
return;
if (widget->property(IS_NULL_PROPERTY).toBool())
widget->setProperty(IS_NULL_PROPERTY, QVariant(false));
func();
@ -786,42 +771,84 @@ static void BindWidgetToIntSetting(SettingsInterface* sif, WidgetType* widget, s
}
}
template<typename T>
static inline void BindWidgetAndLabelToIntSetting(SettingsInterface* sif, T* slider, QLabel* label,
template<typename WidgetType>
static inline void BindWidgetAndLabelToIntSetting(SettingsInterface* sif, WidgetType* widget, QLabel* label,
const QString& label_suffix, std::string section, std::string key,
s32 default_value)
int default_value, int option_offset = 0)
{
using Accessor = SettingAccessor<T>;
using Accessor = SettingAccessor<WidgetType>;
const s32 global_value =
Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), static_cast<s32>(default_value)) - option_offset;
BindWidgetToIntSetting(sif, slider, std::move(section), std::move(key), default_value);
if (sif)
{
QFont orig_font(label->font());
QFont bold_font(orig_font);
bold_font.setBold(true);
Accessor::connectValueChanged(
slider, [slider, label, label_suffix, bold_font = std::move(bold_font), orig_font = std::move(orig_font)]() {
std::optional<int> value = Accessor::getNullableIntValue(slider);
if (value.has_value())
Accessor::makeNullableInt(widget, global_value);
int sif_value;
if (sif->GetIntValue(section.c_str(), key.c_str(), &sif_value))
{
Accessor::setNullableIntValue(widget, sif_value - option_offset);
if (label)
{
label->setText(QStringLiteral("%1%2").arg(sif_value).arg(label_suffix));
label->setFont(bold_font);
}
}
else
{
Accessor::setNullableIntValue(widget, std::nullopt);
if (label)
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
}
Accessor::connectValueChanged(widget, [sif, widget, label, label_suffix, section = std::move(section),
key = std::move(key), option_offset, global_value,
bold_font = std::move(bold_font), orig_font = std::move(orig_font)]() {
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
{
sif->SetIntValue(section.c_str(), key.c_str(), new_value.value() + option_offset);
if (label)
{
label->setFont(bold_font);
label->setText(QStringLiteral("%1%2").arg(value.value()).arg(label_suffix));
label->setText(QStringLiteral("%1%2").arg(new_value.value()).arg(label_suffix));
}
else
}
else
{
sif->DeleteValue(section.c_str(), key.c_str());
if (label)
{
const int global_value = Accessor::getIntValue(slider);
label->setFont(orig_font);
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
}
});
}
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
Accessor::connectValueChanged(slider, [slider, label, label_suffix]() {
const int global_value = Accessor::getIntValue(slider);
Accessor::setIntValue(widget, static_cast<int>(global_value));
if (label)
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
});
Accessor::connectValueChanged(
widget, [widget, label, label_suffix, section = std::move(section), key = std::move(key), option_offset]() {
const int new_value = Accessor::getIntValue(widget);
Host::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset);
Host::CommitBaseSettingChanges();
g_emu_thread->applySettings();
if (label)
label->setText(QStringLiteral("%1%2").arg(new_value).arg(label_suffix));
});
}
}