mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-22 08:20:57 +01:00
configure_audio: Implement ui generation
Needs a considerable amount of management specific to some of the comoboboxes due to the audio engine configuration. general: Partial audio config implmentation configure_audio: Implement ui generation Needs a considerable amount of management specific to some of the comoboboxes due to the audio engine configuration. general: Partial audio config implmentation settings: Make audio settings as enums
This commit is contained in:
parent
88d3de4e85
commit
432f68ad29
14 changed files with 221 additions and 331 deletions
|
@ -15,6 +15,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "audio_core/sink/null_sink.h"
|
#include "audio_core/sink/null_sink.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/settings_enums.h"
|
||||||
|
|
||||||
namespace AudioCore::Sink {
|
namespace AudioCore::Sink {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -24,7 +25,7 @@ struct SinkDetails {
|
||||||
using LatencyFn = u32 (*)();
|
using LatencyFn = u32 (*)();
|
||||||
|
|
||||||
/// Name for this sink.
|
/// Name for this sink.
|
||||||
std::string_view id;
|
Settings::AudioEngine id;
|
||||||
/// A method to call to construct an instance of this type of sink.
|
/// A method to call to construct an instance of this type of sink.
|
||||||
FactoryFn factory;
|
FactoryFn factory;
|
||||||
/// A method to call to list available devices.
|
/// A method to call to list available devices.
|
||||||
|
@ -37,7 +38,7 @@ struct SinkDetails {
|
||||||
constexpr SinkDetails sink_details[] = {
|
constexpr SinkDetails sink_details[] = {
|
||||||
#ifdef HAVE_CUBEB
|
#ifdef HAVE_CUBEB
|
||||||
SinkDetails{
|
SinkDetails{
|
||||||
"cubeb",
|
Settings::AudioEngine::Cubeb,
|
||||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||||
return std::make_unique<CubebSink>(device_id);
|
return std::make_unique<CubebSink>(device_id);
|
||||||
},
|
},
|
||||||
|
@ -47,7 +48,7 @@ constexpr SinkDetails sink_details[] = {
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
SinkDetails{
|
SinkDetails{
|
||||||
"sdl2",
|
Settings::AudioEngine::Sdl2,
|
||||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||||
return std::make_unique<SDLSink>(device_id);
|
return std::make_unique<SDLSink>(device_id);
|
||||||
},
|
},
|
||||||
|
@ -55,46 +56,46 @@ constexpr SinkDetails sink_details[] = {
|
||||||
&GetSDLLatency,
|
&GetSDLLatency,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
SinkDetails{"null",
|
SinkDetails{Settings::AudioEngine::Null,
|
||||||
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
[](std::string_view device_id) -> std::unique_ptr<Sink> {
|
||||||
return std::make_unique<NullSink>(device_id);
|
return std::make_unique<NullSink>(device_id);
|
||||||
},
|
},
|
||||||
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
|
[](bool capture) { return std::vector<std::string>{"null"}; }, []() { return 0u; }},
|
||||||
};
|
};
|
||||||
|
|
||||||
const SinkDetails& GetOutputSinkDetails(std::string_view sink_id) {
|
const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
|
||||||
const auto find_backend{[](std::string_view id) {
|
const auto find_backend{[](Settings::AudioEngine id) {
|
||||||
return std::find_if(std::begin(sink_details), std::end(sink_details),
|
return std::find_if(std::begin(sink_details), std::end(sink_details),
|
||||||
[&id](const auto& sink_detail) { return sink_detail.id == id; });
|
[&id](const auto& sink_detail) { return sink_detail.id == id; });
|
||||||
}};
|
}};
|
||||||
|
|
||||||
auto iter = find_backend(sink_id);
|
auto iter = find_backend(sink_id);
|
||||||
|
|
||||||
if (sink_id == "auto") {
|
if (sink_id == Settings::AudioEngine::Auto) {
|
||||||
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
|
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
|
||||||
// causes audio issues, in that case go with SDL.
|
// causes audio issues, in that case go with SDL.
|
||||||
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
|
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
|
||||||
iter = find_backend("cubeb");
|
iter = find_backend(Settings::AudioEngine::Cubeb);
|
||||||
if (iter->latency() > TargetSampleCount * 3) {
|
if (iter->latency() > TargetSampleCount * 3) {
|
||||||
iter = find_backend("sdl2");
|
iter = find_backend(Settings::AudioEngine::Sdl2);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
iter = std::begin(sink_details);
|
iter = std::begin(sink_details);
|
||||||
#endif
|
#endif
|
||||||
LOG_INFO(Service_Audio, "Auto-selecting the {} backend", iter->id);
|
LOG_INFO(Service_Audio, "Auto-selecting the {} backend", Settings::TranslateEnum(iter->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter == std::end(sink_details)) {
|
if (iter == std::end(sink_details)) {
|
||||||
LOG_ERROR(Audio, "Invalid sink_id {}", sink_id);
|
LOG_ERROR(Audio, "Invalid sink_id {}", Settings::TranslateEnum(sink_id));
|
||||||
iter = find_backend("null");
|
iter = find_backend(Settings::AudioEngine::Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *iter;
|
return *iter;
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
std::vector<std::string_view> GetSinkIDs() {
|
std::vector<Settings::AudioEngine> GetSinkIDs() {
|
||||||
std::vector<std::string_view> sink_ids(std::size(sink_details));
|
std::vector<Settings::AudioEngine> sink_ids(std::size(sink_details));
|
||||||
|
|
||||||
std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids),
|
std::transform(std::begin(sink_details), std::end(sink_details), std::begin(sink_ids),
|
||||||
[](const auto& sink) { return sink.id; });
|
[](const auto& sink) { return sink.id; });
|
||||||
|
@ -102,11 +103,11 @@ std::vector<std::string_view> GetSinkIDs() {
|
||||||
return sink_ids;
|
return sink_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture) {
|
std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture) {
|
||||||
return GetOutputSinkDetails(sink_id).list_devices(capture);
|
return GetOutputSinkDetails(sink_id).list_devices(capture);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id) {
|
std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id) {
|
||||||
return GetOutputSinkDetails(sink_id).factory(device_id);
|
return GetOutputSinkDetails(sink_id).factory(device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Settings {
|
||||||
|
enum class AudioEngine : u32;
|
||||||
|
}
|
||||||
namespace AudioCore {
|
namespace AudioCore {
|
||||||
class AudioManager;
|
class AudioManager;
|
||||||
|
|
||||||
|
@ -19,7 +22,7 @@ class Sink;
|
||||||
*
|
*
|
||||||
* @return Vector of available sink names.
|
* @return Vector of available sink names.
|
||||||
*/
|
*/
|
||||||
std::vector<std::string_view> GetSinkIDs();
|
std::vector<Settings::AudioEngine> GetSinkIDs();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the list of devices for a particular sink identified by the given ID.
|
* Gets the list of devices for a particular sink identified by the given ID.
|
||||||
|
@ -28,7 +31,7 @@ std::vector<std::string_view> GetSinkIDs();
|
||||||
* @param capture - Get capture (input) devices, or output devices?
|
* @param capture - Get capture (input) devices, or output devices?
|
||||||
* @return Vector of device names.
|
* @return Vector of device names.
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool capture);
|
std::vector<std::string> GetDeviceListForSink(Settings::AudioEngine sink_id, bool capture);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an audio sink identified by the given device ID.
|
* Creates an audio sink identified by the given device ID.
|
||||||
|
@ -37,7 +40,7 @@ std::vector<std::string> GetDeviceListForSink(std::string_view sink_id, bool cap
|
||||||
* @param device_id - Name of the device to create.
|
* @param device_id - Name of the device to create.
|
||||||
* @return Pointer to the created sink.
|
* @return Pointer to the created sink.
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<Sink> CreateSinkFromID(std::string_view sink_id, std::string_view device_id);
|
std::unique_ptr<Sink> CreateSinkFromID(Settings::AudioEngine sink_id, std::string_view device_id);
|
||||||
|
|
||||||
} // namespace Sink
|
} // namespace Sink
|
||||||
} // namespace AudioCore
|
} // namespace AudioCore
|
||||||
|
|
|
@ -90,7 +90,7 @@ void LogSettings() {
|
||||||
log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue());
|
log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue());
|
||||||
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
|
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
|
||||||
log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
|
log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
|
||||||
log_setting("Audio_OutputEngine", values.sink_id.GetValue());
|
log_setting("Audio_OutputEngine", Settings::TranslateEnum(values.sink_id.GetValue()));
|
||||||
log_setting("Audio_OutputDevice", values.audio_output_device_id.GetValue());
|
log_setting("Audio_OutputDevice", values.audio_output_device_id.GetValue());
|
||||||
log_setting("Audio_InputDevice", values.audio_input_device_id.GetValue());
|
log_setting("Audio_InputDevice", values.audio_input_device_id.GetValue());
|
||||||
log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue());
|
log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue());
|
||||||
|
|
|
@ -244,6 +244,8 @@ protected:
|
||||||
return value_.has_value() ? std::to_string(*value_) : "none";
|
return value_.has_value() ? std::to_string(*value_) : "none";
|
||||||
} else if constexpr (std::is_same<Type, bool>()) {
|
} else if constexpr (std::is_same<Type, bool>()) {
|
||||||
return value_ ? "true" : "false";
|
return value_ ? "true" : "false";
|
||||||
|
} else if (std::is_same<Type, AudioEngine>()) {
|
||||||
|
return TranslateEnum(value_);
|
||||||
} else {
|
} else {
|
||||||
return std::to_string(static_cast<u64>(value_));
|
return std::to_string(static_cast<u64>(value_));
|
||||||
}
|
}
|
||||||
|
@ -309,6 +311,8 @@ public:
|
||||||
this->SetValue(static_cast<u32>(std::stoul(input)));
|
this->SetValue(static_cast<u32>(std::stoul(input)));
|
||||||
} else if constexpr (std::is_same<Type, bool>()) {
|
} else if constexpr (std::is_same<Type, bool>()) {
|
||||||
this->SetValue(input == "true");
|
this->SetValue(input == "true");
|
||||||
|
} else if constexpr (std::is_same<Type, AudioEngine>()) {
|
||||||
|
this->SetValue(ToEnum<Type>(input));
|
||||||
} else {
|
} else {
|
||||||
this->SetValue(static_cast<Type>(std::stoll(input)));
|
this->SetValue(static_cast<Type>(std::stoll(input)));
|
||||||
}
|
}
|
||||||
|
@ -542,7 +546,7 @@ struct Values {
|
||||||
Linkage linkage{};
|
Linkage linkage{};
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Setting<std::string> sink_id{linkage, "auto", "output_engine", Category::Audio};
|
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio};
|
||||||
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio};
|
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio};
|
||||||
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio};
|
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio};
|
||||||
Setting<bool, false> audio_muted{linkage, false, "audio_muted", Category::Audio, false};
|
Setting<bool, false> audio_muted{linkage, false, "audio_muted", Category::Audio, false};
|
||||||
|
@ -731,8 +735,9 @@ struct Values {
|
||||||
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto,
|
||||||
TimeZone::Auto, TimeZone::Zulu,
|
TimeZone::Auto, TimeZone::Zulu,
|
||||||
"time_zone_index", Category::System};
|
"time_zone_index", Category::System};
|
||||||
SwitchableSetting<s32, true> sound_index{
|
SwitchableSetting<AudioMode, true> sound_index{linkage, AudioMode::Stereo,
|
||||||
linkage, 1, 0, 2, "sound_index", Category::SystemAudio};
|
AudioMode::Mono, AudioMode::Surround,
|
||||||
|
"sound_index", Category::SystemAudio};
|
||||||
|
|
||||||
SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
|
SwitchableSetting<bool> use_docked_mode{linkage, true, "use_docked_mode", Category::System};
|
||||||
|
|
||||||
|
|
|
@ -254,7 +254,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
|
||||||
|
|
||||||
// Log user configuration information
|
// Log user configuration information
|
||||||
constexpr auto field_type = Telemetry::FieldType::UserConfig;
|
constexpr auto field_type = Telemetry::FieldType::UserConfig;
|
||||||
AddField(field_type, "Audio_SinkId", Settings::values.sink_id.GetValue());
|
AddField(field_type, "Audio_SinkId",
|
||||||
|
Settings::TranslateEnum(Settings::values.sink_id.GetValue()));
|
||||||
AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue());
|
AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue());
|
||||||
AddField(field_type, "Renderer_Backend",
|
AddField(field_type, "Renderer_Backend",
|
||||||
TranslateRenderer(Settings::values.renderer_backend.GetValue()));
|
TranslateRenderer(Settings::values.renderer_backend.GetValue()));
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <forward_list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "audio_core/sink/sink.h"
|
#include "audio_core/sink/sink.h"
|
||||||
|
@ -10,80 +11,105 @@
|
||||||
#include "ui_configure_audio.h"
|
#include "ui_configure_audio.h"
|
||||||
#include "yuzu/configuration/configuration_shared.h"
|
#include "yuzu/configuration/configuration_shared.h"
|
||||||
#include "yuzu/configuration/configure_audio.h"
|
#include "yuzu/configuration/configure_audio.h"
|
||||||
|
#include "yuzu/configuration/shared_translation.h"
|
||||||
|
#include "yuzu/configuration/shared_widget.h"
|
||||||
#include "yuzu/uisettings.h"
|
#include "yuzu/uisettings.h"
|
||||||
|
|
||||||
ConfigureAudio::ConfigureAudio(const Core::System& system_,
|
ConfigureAudio::ConfigureAudio(const Core::System& system_,
|
||||||
std::shared_ptr<std::forward_list<ConfigurationShared::Tab*>> group,
|
std::shared_ptr<std::forward_list<ConfigurationShared::Tab*>> group,
|
||||||
|
const ConfigurationShared::TranslationMap& translations_,
|
||||||
QWidget* parent)
|
QWidget* parent)
|
||||||
: Tab(group, parent), ui(std::make_unique<Ui::ConfigureAudio>()), system{system_} {
|
: Tab(group, parent),
|
||||||
|
ui(std::make_unique<Ui::ConfigureAudio>()), system{system_}, translations{translations_} {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
Setup();
|
||||||
InitializeAudioSinkComboBox();
|
|
||||||
|
|
||||||
connect(ui->volume_slider, &QSlider::valueChanged, this,
|
|
||||||
&ConfigureAudio::SetVolumeIndicatorText);
|
|
||||||
connect(ui->sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
|
||||||
&ConfigureAudio::UpdateAudioDevices);
|
|
||||||
|
|
||||||
ui->volume_label->setVisible(Settings::IsConfiguringGlobal());
|
|
||||||
ui->volume_combo_box->setVisible(!Settings::IsConfiguringGlobal());
|
|
||||||
|
|
||||||
SetupPerGameUI();
|
|
||||||
|
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
|
|
||||||
const bool is_powered_on = system_.IsPoweredOn();
|
|
||||||
ui->sink_combo_box->setEnabled(!is_powered_on);
|
|
||||||
ui->output_combo_box->setEnabled(!is_powered_on);
|
|
||||||
ui->input_combo_box->setEnabled(!is_powered_on);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureAudio::~ConfigureAudio() = default;
|
ConfigureAudio::~ConfigureAudio() = default;
|
||||||
|
|
||||||
|
void ConfigureAudio::Setup() {
|
||||||
|
const bool runtime_lock = !system.IsPoweredOn();
|
||||||
|
auto& layout = *ui->audio_widget->layout();
|
||||||
|
|
||||||
|
std::forward_list<Settings::BasicSetting*> settings;
|
||||||
|
|
||||||
|
auto push = [&](Settings::Category category) {
|
||||||
|
for (auto* setting : Settings::values.linkage.by_category[category]) {
|
||||||
|
settings.push_front(setting);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
push(Settings::Category::Audio);
|
||||||
|
push(Settings::Category::SystemAudio);
|
||||||
|
|
||||||
|
for (auto* setting : settings) {
|
||||||
|
auto* widget = [&]() {
|
||||||
|
if (setting->Id() == Settings::values.volume.Id()) {
|
||||||
|
return new ConfigurationShared::Widget(
|
||||||
|
setting, translations, this, runtime_lock, apply_funcs,
|
||||||
|
ConfigurationShared::RequestType::Slider, true, 1.0f, nullptr,
|
||||||
|
tr("%1%", "Volume percentage (e.g. 50%)"));
|
||||||
|
} else if (setting->Id() == Settings::values.audio_output_device_id.Id() ||
|
||||||
|
setting->Id() == Settings::values.audio_input_device_id.Id() ||
|
||||||
|
setting->Id() == Settings::values.sink_id.Id()) {
|
||||||
|
return new ConfigurationShared::Widget(
|
||||||
|
setting, translations, this, runtime_lock, apply_funcs,
|
||||||
|
ConfigurationShared::RequestType::ComboBox, false);
|
||||||
|
} else {
|
||||||
|
return new ConfigurationShared::Widget(setting, translations, this, runtime_lock,
|
||||||
|
apply_funcs);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (!widget->Valid()) {
|
||||||
|
delete widget;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.addWidget(widget);
|
||||||
|
|
||||||
|
if (setting->Id() == Settings::values.sink_id.Id()) {
|
||||||
|
sink_combo_box = widget->combobox;
|
||||||
|
InitializeAudioSinkComboBox();
|
||||||
|
|
||||||
|
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
|
&ConfigureAudio::UpdateAudioDevices);
|
||||||
|
} else if (setting->Id() == Settings::values.audio_output_device_id.Id()) {
|
||||||
|
output_device_combo_box = widget->combobox;
|
||||||
|
} else if (setting->Id() == Settings::values.audio_input_device_id.Id()) {
|
||||||
|
input_device_combo_box = widget->combobox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetConfiguration() {
|
void ConfigureAudio::SetConfiguration() {
|
||||||
|
if (!Settings::IsConfiguringGlobal()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SetOutputSinkFromSinkID();
|
SetOutputSinkFromSinkID();
|
||||||
|
|
||||||
// The device list cannot be pre-populated (nor listed) until the output sink is known.
|
// The device list cannot be pre-populated (nor listed) until the output sink is known.
|
||||||
UpdateAudioDevices(ui->sink_combo_box->currentIndex());
|
UpdateAudioDevices(sink_combo_box->currentIndex());
|
||||||
|
|
||||||
SetAudioDevicesFromDeviceID();
|
SetAudioDevicesFromDeviceID();
|
||||||
|
|
||||||
const auto volume_value = static_cast<int>(Settings::values.volume.GetValue());
|
|
||||||
ui->volume_slider->setValue(volume_value);
|
|
||||||
ui->toggle_background_mute->setChecked(UISettings::values.mute_when_in_background.GetValue());
|
|
||||||
|
|
||||||
if (!Settings::IsConfiguringGlobal()) {
|
|
||||||
if (Settings::values.volume.UsingGlobal()) {
|
|
||||||
ui->volume_combo_box->setCurrentIndex(0);
|
|
||||||
ui->volume_slider->setEnabled(false);
|
|
||||||
} else {
|
|
||||||
ui->volume_combo_box->setCurrentIndex(1);
|
|
||||||
ui->volume_slider->setEnabled(true);
|
|
||||||
}
|
|
||||||
ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index);
|
|
||||||
ConfigurationShared::SetHighlight(ui->mode_label,
|
|
||||||
!Settings::values.sound_index.UsingGlobal());
|
|
||||||
ConfigurationShared::SetHighlight(ui->volume_layout,
|
|
||||||
!Settings::values.volume.UsingGlobal());
|
|
||||||
} else {
|
|
||||||
ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue());
|
|
||||||
}
|
|
||||||
SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
||||||
[[maybe_unused]] const QSignalBlocker blocker(ui->sink_combo_box);
|
[[maybe_unused]] const QSignalBlocker blocker(sink_combo_box);
|
||||||
|
|
||||||
int new_sink_index = 0;
|
int new_sink_index = 0;
|
||||||
const QString sink_id = QString::fromStdString(Settings::values.sink_id.GetValue());
|
const QString sink_id = QString::fromStdString(Settings::values.sink_id.ToString());
|
||||||
for (int index = 0; index < ui->sink_combo_box->count(); index++) {
|
for (int index = 0; index < sink_combo_box->count(); index++) {
|
||||||
if (ui->sink_combo_box->itemText(index) == sink_id) {
|
if (sink_combo_box->itemText(index) == sink_id) {
|
||||||
new_sink_index = index;
|
new_sink_index = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->sink_combo_box->setCurrentIndex(new_sink_index);
|
sink_combo_box->setCurrentIndex(new_sink_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
||||||
|
@ -91,57 +117,42 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
||||||
|
|
||||||
const QString output_device_id =
|
const QString output_device_id =
|
||||||
QString::fromStdString(Settings::values.audio_output_device_id.GetValue());
|
QString::fromStdString(Settings::values.audio_output_device_id.GetValue());
|
||||||
for (int index = 0; index < ui->output_combo_box->count(); index++) {
|
for (int index = 0; index < output_device_combo_box->count(); index++) {
|
||||||
if (ui->output_combo_box->itemText(index) == output_device_id) {
|
if (output_device_combo_box->itemText(index) == output_device_id) {
|
||||||
new_device_index = index;
|
new_device_index = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->output_combo_box->setCurrentIndex(new_device_index);
|
output_device_combo_box->setCurrentIndex(new_device_index);
|
||||||
|
|
||||||
new_device_index = -1;
|
new_device_index = -1;
|
||||||
const QString input_device_id =
|
const QString input_device_id =
|
||||||
QString::fromStdString(Settings::values.audio_input_device_id.GetValue());
|
QString::fromStdString(Settings::values.audio_input_device_id.GetValue());
|
||||||
for (int index = 0; index < ui->input_combo_box->count(); index++) {
|
for (int index = 0; index < input_device_combo_box->count(); index++) {
|
||||||
if (ui->input_combo_box->itemText(index) == input_device_id) {
|
if (input_device_combo_box->itemText(index) == input_device_id) {
|
||||||
new_device_index = index;
|
new_device_index = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->input_combo_box->setCurrentIndex(new_device_index);
|
input_device_combo_box->setCurrentIndex(new_device_index);
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureAudio::SetVolumeIndicatorText(int percentage) {
|
|
||||||
ui->volume_indicator->setText(tr("%1%", "Volume percentage (e.g. 50%)").arg(percentage));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::ApplyConfiguration() {
|
void ConfigureAudio::ApplyConfiguration() {
|
||||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
|
const bool is_powered_on = system.IsPoweredOn();
|
||||||
|
for (const auto& apply_func : apply_funcs) {
|
||||||
|
apply_func(is_powered_on);
|
||||||
|
}
|
||||||
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
Settings::values.sink_id =
|
Settings::values.sink_id.LoadString(
|
||||||
ui->sink_combo_box->itemText(ui->sink_combo_box->currentIndex()).toStdString();
|
sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
|
||||||
Settings::values.audio_output_device_id.SetValue(
|
Settings::values.audio_output_device_id.SetValue(
|
||||||
ui->output_combo_box->itemText(ui->output_combo_box->currentIndex()).toStdString());
|
output_device_combo_box->itemText(output_device_combo_box->currentIndex())
|
||||||
|
.toStdString());
|
||||||
Settings::values.audio_input_device_id.SetValue(
|
Settings::values.audio_input_device_id.SetValue(
|
||||||
ui->input_combo_box->itemText(ui->input_combo_box->currentIndex()).toStdString());
|
input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString());
|
||||||
UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();
|
|
||||||
|
|
||||||
// Guard if during game and set to game-specific value
|
|
||||||
if (Settings::values.volume.UsingGlobal()) {
|
|
||||||
const auto volume = static_cast<u8>(ui->volume_slider->value());
|
|
||||||
Settings::values.volume.SetValue(volume);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ui->volume_combo_box->currentIndex() == 0) {
|
|
||||||
Settings::values.volume.SetGlobal(true);
|
|
||||||
} else {
|
|
||||||
Settings::values.volume.SetGlobal(false);
|
|
||||||
const auto volume = static_cast<u8>(ui->volume_slider->value());
|
|
||||||
Settings::values.volume.SetValue(volume);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,54 +165,31 @@ void ConfigureAudio::changeEvent(QEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
||||||
ui->output_combo_box->clear();
|
output_device_combo_box->clear();
|
||||||
ui->output_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
||||||
|
|
||||||
const std::string sink_id = ui->sink_combo_box->itemText(sink_index).toStdString();
|
const auto sink_id =
|
||||||
|
Settings::ToEnum<Settings::AudioEngine>(sink_combo_box->itemText(sink_index).toStdString());
|
||||||
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, false)) {
|
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, false)) {
|
||||||
ui->output_combo_box->addItem(QString::fromStdString(device));
|
output_device_combo_box->addItem(QString::fromStdString(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->input_combo_box->clear();
|
input_device_combo_box->clear();
|
||||||
ui->input_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
input_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
||||||
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) {
|
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) {
|
||||||
ui->input_combo_box->addItem(QString::fromStdString(device));
|
input_device_combo_box->addItem(QString::fromStdString(device));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::InitializeAudioSinkComboBox() {
|
void ConfigureAudio::InitializeAudioSinkComboBox() {
|
||||||
ui->sink_combo_box->clear();
|
sink_combo_box->clear();
|
||||||
ui->sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
sink_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
||||||
|
|
||||||
for (const auto& id : AudioCore::Sink::GetSinkIDs()) {
|
for (const auto& id : AudioCore::Sink::GetSinkIDs()) {
|
||||||
ui->sink_combo_box->addItem(QString::fromUtf8(id.data(), static_cast<s32>(id.length())));
|
sink_combo_box->addItem(QString::fromStdString(Settings::TranslateEnum(id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureAudio::RetranslateUI() {
|
void ConfigureAudio::RetranslateUI() {
|
||||||
ui->retranslateUi(this);
|
ui->retranslateUi(this);
|
||||||
SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureAudio::SetupPerGameUI() {
|
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
|
||||||
ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal());
|
|
||||||
ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->mode_label,
|
|
||||||
Settings::values.sound_index.GetValue(true));
|
|
||||||
|
|
||||||
connect(ui->volume_combo_box, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
|
||||||
ui->volume_slider->setEnabled(index == 1);
|
|
||||||
ConfigurationShared::SetHighlight(ui->volume_layout, index == 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
ui->sink_combo_box->setVisible(false);
|
|
||||||
ui->sink_label->setVisible(false);
|
|
||||||
ui->output_combo_box->setVisible(false);
|
|
||||||
ui->output_label->setVisible(false);
|
|
||||||
ui->input_combo_box->setVisible(false);
|
|
||||||
ui->input_label->setVisible(false);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <forward_list>
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include "yuzu/configuration/configuration_shared.h"
|
#include "yuzu/configuration/configuration_shared.h"
|
||||||
|
#include "yuzu/configuration/shared_translation.h"
|
||||||
|
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class System;
|
class System;
|
||||||
|
@ -19,6 +24,7 @@ class ConfigureAudio : public ConfigurationShared::Tab {
|
||||||
public:
|
public:
|
||||||
explicit ConfigureAudio(const Core::System& system_,
|
explicit ConfigureAudio(const Core::System& system_,
|
||||||
std::shared_ptr<std::forward_list<ConfigurationShared::Tab*>> group,
|
std::shared_ptr<std::forward_list<ConfigurationShared::Tab*>> group,
|
||||||
|
const ConfigurationShared::TranslationMap& translations_,
|
||||||
QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
~ConfigureAudio() override;
|
~ConfigureAudio() override;
|
||||||
|
|
||||||
|
@ -36,11 +42,17 @@ private:
|
||||||
|
|
||||||
void SetOutputSinkFromSinkID();
|
void SetOutputSinkFromSinkID();
|
||||||
void SetAudioDevicesFromDeviceID();
|
void SetAudioDevicesFromDeviceID();
|
||||||
void SetVolumeIndicatorText(int percentage);
|
|
||||||
|
|
||||||
void SetupPerGameUI();
|
void Setup();
|
||||||
|
|
||||||
std::unique_ptr<Ui::ConfigureAudio> ui;
|
std::unique_ptr<Ui::ConfigureAudio> ui;
|
||||||
|
|
||||||
const Core::System& system;
|
const Core::System& system;
|
||||||
|
const ConfigurationShared::TranslationMap& translations;
|
||||||
|
|
||||||
|
std::forward_list<std::function<void(bool)>> apply_funcs{};
|
||||||
|
|
||||||
|
QComboBox* sink_combo_box;
|
||||||
|
QComboBox* output_device_combo_box;
|
||||||
|
QComboBox* input_device_combo_box;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,80 +21,14 @@
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout">
|
<layout class="QVBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="engine_layout">
|
<widget class="QWidget" name="audio_widget" native="true">
|
||||||
<item>
|
<property name="maximumSize">
|
||||||
<widget class="QLabel" name="sink_label">
|
<size>
|
||||||
<property name="text">
|
<width>16777215</width>
|
||||||
<string>Output Engine:</string>
|
<height>16777213</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="sink_combo_box"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="output_layout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="output_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Output Device:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="output_combo_box"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="input_layout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="input_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Input Device:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="input_combo_box"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="mode_layout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="mode_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Sound Output Mode:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="combo_sound">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Mono</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Stereo</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Surround</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="volume_layout" native="true">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
|
@ -107,89 +41,9 @@
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="volume_combo_box">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Use global volume</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Set volume:</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="volume_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Volume:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>30</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="volume_slider">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>200</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="volume_indicator">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>32</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>0 %</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="mute_layout">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="toggle_background_mute">
|
|
||||||
<property name="text">
|
|
||||||
<string>Mute audio when in background</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -34,7 +34,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
|
||||||
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()},
|
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()},
|
||||||
registry(registry_), system{system_},
|
registry(registry_), system{system_},
|
||||||
translations{ConfigurationShared::InitializeTranslations(this)},
|
translations{ConfigurationShared::InitializeTranslations(this)},
|
||||||
audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, this)},
|
audio_tab{std::make_unique<ConfigureAudio>(system_, nullptr, *translations, this)},
|
||||||
cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, this)},
|
cpu_tab{std::make_unique<ConfigureCpu>(system_, nullptr, this)},
|
||||||
debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
|
debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
|
||||||
filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
|
filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
|
||||||
|
|
|
@ -240,12 +240,14 @@ void ConfigureGraphics::Setup() {
|
||||||
} else if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) {
|
} else if (setting->Id() == Settings::values.fsr_sharpening_slider.Id()) {
|
||||||
return new ConfigurationShared::Widget(
|
return new ConfigurationShared::Widget(
|
||||||
setting, translations, this, runtime_lock, apply_funcs,
|
setting, translations, this, runtime_lock, apply_funcs,
|
||||||
ConfigurationShared::RequestType::ReverseSlider, true, 0.5f);
|
ConfigurationShared::RequestType::ReverseSlider, true, 0.5f, nullptr,
|
||||||
|
tr("%1%", "FSR sharpening percentage (e.g. 50%)"));
|
||||||
} else if (setting->Id() == Settings::values.speed_limit.Id()) {
|
} else if (setting->Id() == Settings::values.speed_limit.Id()) {
|
||||||
return new ConfigurationShared::Widget(
|
return new ConfigurationShared::Widget(
|
||||||
setting, translations, this, runtime_lock, apply_funcs,
|
setting, translations, this, runtime_lock, apply_funcs,
|
||||||
ConfigurationShared::RequestType::SpinBox, true, 1.0f,
|
ConfigurationShared::RequestType::SpinBox, true, 1.0f,
|
||||||
&Settings::values.use_speed_limit, "%");
|
&Settings::values.use_speed_limit,
|
||||||
|
tr("%", "Limit speed percentage (e.g. 50%)"));
|
||||||
} else {
|
} else {
|
||||||
return new ConfigurationShared::Widget(setting, translations, this, runtime_lock,
|
return new ConfigurationShared::Widget(setting, translations, this, runtime_lock,
|
||||||
apply_funcs);
|
apply_funcs);
|
||||||
|
@ -304,7 +306,7 @@ void ConfigureGraphics::Setup() {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
QPushButton* bg_restore_button = ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
QPushButton* bg_restore_button = ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||||
Settings::values.bg_red, ui->bg_widget);
|
Settings::values.bg_red.UsingGlobal(), ui->bg_widget);
|
||||||
ui->bg_widget->layout()->addWidget(bg_restore_button);
|
ui->bg_widget->layout()->addWidget(bg_restore_button);
|
||||||
|
|
||||||
QObject::connect(bg_restore_button, &QAbstractButton::clicked,
|
QObject::connect(bg_restore_button, &QAbstractButton::clicked,
|
||||||
|
|
|
@ -50,7 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
|
||||||
game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
|
game_config = std::make_unique<Config>(config_file_name, Config::ConfigType::PerGameConfig);
|
||||||
|
|
||||||
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
|
addons_tab = std::make_unique<ConfigurePerGameAddons>(system_, this);
|
||||||
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, this);
|
audio_tab = std::make_unique<ConfigureAudio>(system_, tab_group, *translations, this);
|
||||||
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, this);
|
cpu_tab = std::make_unique<ConfigureCpu>(system_, tab_group, this);
|
||||||
graphics_advanced_tab =
|
graphics_advanced_tab =
|
||||||
std::make_unique<ConfigureGraphicsAdvanced>(system_, tab_group, *translations, this);
|
std::make_unique<ConfigureGraphicsAdvanced>(system_, tab_group, *translations, this);
|
||||||
|
|
|
@ -30,6 +30,7 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
|
||||||
INSERT(Settings, audio_input_device_id, "Input Device:", "");
|
INSERT(Settings, audio_input_device_id, "Input Device:", "");
|
||||||
INSERT(Settings, audio_muted, "Mute audio when in background", "");
|
INSERT(Settings, audio_muted, "Mute audio when in background", "");
|
||||||
INSERT(Settings, volume, "Volume:", "");
|
INSERT(Settings, volume, "Volume:", "");
|
||||||
|
INSERT(Settings, dump_audio_commands, "", "");
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
INSERT(Settings, use_multi_core, "Multicore CPU Emulation", "");
|
INSERT(Settings, use_multi_core, "Multicore CPU Emulation", "");
|
||||||
|
@ -270,6 +271,12 @@ std::forward_list<QString> ComboboxEnumeration(std::type_index type, QWidget* pa
|
||||||
tr("ROC"), tr("ROK"), tr("Singapore"), tr("Turkey"), tr("UCT"),
|
tr("ROC"), tr("ROK"), tr("Singapore"), tr("Turkey"), tr("UCT"),
|
||||||
tr("W-SU"), tr("WET"), tr("Zulu"),
|
tr("W-SU"), tr("WET"), tr("Zulu"),
|
||||||
};
|
};
|
||||||
|
} else if (type == typeid(Settings::AudioMode)) {
|
||||||
|
return {
|
||||||
|
tr("Mono"),
|
||||||
|
tr("Stereo"),
|
||||||
|
tr("Surround"),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
namespace ConfigurationShared {
|
namespace ConfigurationShared {
|
||||||
|
|
||||||
QPushButton* Widget::CreateRestoreGlobalButton(Settings::BasicSetting& setting, QWidget* parent) {
|
QPushButton* Widget::CreateRestoreGlobalButton(bool using_global, QWidget* parent) {
|
||||||
QStyle* style = parent->style();
|
QStyle* style = parent->style();
|
||||||
QIcon* icon = new QIcon(style->standardIcon(QStyle::SP_LineEditClearButton));
|
QIcon* icon = new QIcon(style->standardIcon(QStyle::SP_LineEditClearButton));
|
||||||
QPushButton* restore_button = new QPushButton(*icon, QStringLiteral(""), parent);
|
QPushButton* restore_button = new QPushButton(*icon, QStringLiteral(""), parent);
|
||||||
|
@ -34,8 +34,8 @@ QPushButton* Widget::CreateRestoreGlobalButton(Settings::BasicSetting& setting,
|
||||||
sp_retain.setRetainSizeWhenHidden(true);
|
sp_retain.setRetainSizeWhenHidden(true);
|
||||||
restore_button->setSizePolicy(sp_retain);
|
restore_button->setSizePolicy(sp_retain);
|
||||||
|
|
||||||
restore_button->setEnabled(!setting.UsingGlobal());
|
restore_button->setEnabled(!using_global);
|
||||||
restore_button->setVisible(!setting.UsingGlobal());
|
restore_button->setVisible(!using_global);
|
||||||
|
|
||||||
return restore_button;
|
return restore_button;
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,10 @@ QHBoxLayout* Widget::CreateCheckBox(Settings::BasicSetting* bool_setting, const
|
||||||
: Qt::CheckState::Unchecked);
|
: Qt::CheckState::Unchecked);
|
||||||
checkbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
checkbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
|
||||||
|
if (!bool_setting->Save() && !Settings::IsConfiguringGlobal() && runtime_lock) {
|
||||||
|
checkbox->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
layout->addWidget(checkbox);
|
layout->addWidget(checkbox);
|
||||||
|
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
@ -70,7 +74,8 @@ QHBoxLayout* Widget::CreateCheckBox(Settings::BasicSetting* bool_setting, const
|
||||||
bool_setting->LoadString(checkbox->checkState() == Qt::Checked ? "true" : "false");
|
bool_setting->LoadString(checkbox->checkState() == Qt::Checked ? "true" : "false");
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
restore_button = CreateRestoreGlobalButton(*bool_setting, this);
|
restore_button =
|
||||||
|
CreateRestoreGlobalButton(bool_setting->UsingGlobal() && setting.UsingGlobal(), this);
|
||||||
layout->addWidget(restore_button);
|
layout->addWidget(restore_button);
|
||||||
|
|
||||||
QObject::connect(checkbox, &QCheckBox::stateChanged, [=](int) {
|
QObject::connect(checkbox, &QCheckBox::stateChanged, [=](int) {
|
||||||
|
@ -128,7 +133,7 @@ void Widget::CreateCombobox(const QString& label, std::function<void()>& load_fu
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
load_func = [=]() { setting.LoadString(std::to_string(combobox->currentIndex())); };
|
load_func = [=]() { setting.LoadString(std::to_string(combobox->currentIndex())); };
|
||||||
} else {
|
} else {
|
||||||
restore_button = CreateRestoreGlobalButton(setting, this);
|
restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this);
|
||||||
layout->addWidget(restore_button);
|
layout->addWidget(restore_button);
|
||||||
|
|
||||||
QObject::connect(restore_button, &QAbstractButton::clicked, [&](bool) {
|
QObject::connect(restore_button, &QAbstractButton::clicked, [&](bool) {
|
||||||
|
@ -194,7 +199,7 @@ void Widget::CreateLineEdit(const QString& label, std::function<void()>& load_fu
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (!has_checkbox) {
|
if (!has_checkbox) {
|
||||||
restore_button = CreateRestoreGlobalButton(setting, this);
|
restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this);
|
||||||
layout->addWidget(restore_button);
|
layout->addWidget(restore_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +228,7 @@ void Widget::CreateLineEdit(const QString& label, std::function<void()>& load_fu
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::CreateSlider(const QString& label, bool reversed, float multiplier,
|
void Widget::CreateSlider(const QString& label, bool reversed, float multiplier,
|
||||||
std::function<void()>& load_func, bool managed,
|
std::function<void()>& load_func, bool managed, const QString& format,
|
||||||
Settings::BasicSetting* const other_setting) {
|
Settings::BasicSetting* const other_setting) {
|
||||||
created = true;
|
created = true;
|
||||||
|
|
||||||
|
@ -242,15 +247,16 @@ void Widget::CreateSlider(const QString& label, bool reversed, float multiplier,
|
||||||
|
|
||||||
int max_val = std::stoi(setting.MaxVal());
|
int max_val = std::stoi(setting.MaxVal());
|
||||||
|
|
||||||
|
const QString use_format = format == QStringLiteral("") ? QStringLiteral("%1") : format;
|
||||||
|
|
||||||
QObject::connect(slider, &QAbstractSlider::valueChanged, [=](int value) {
|
QObject::connect(slider, &QAbstractSlider::valueChanged, [=](int value) {
|
||||||
int present = (reversed ? max_val - value : value) * multiplier;
|
int present = (reversed ? max_val - value : value) * multiplier + 0.5f;
|
||||||
feedback->setText(
|
feedback->setText(use_format.arg(QVariant::fromValue(present).value<QString>()));
|
||||||
QStringLiteral("%1%").arg(QString::fromStdString(std::to_string(present))));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
slider->setValue(std::stoi(setting.ToString()));
|
|
||||||
slider->setMinimum(std::stoi(setting.MinVal()));
|
slider->setMinimum(std::stoi(setting.MinVal()));
|
||||||
slider->setMaximum(max_val);
|
slider->setMaximum(max_val);
|
||||||
|
slider->setValue(std::stoi(setting.ToString()));
|
||||||
|
|
||||||
slider->setInvertedAppearance(reversed);
|
slider->setInvertedAppearance(reversed);
|
||||||
|
|
||||||
|
@ -261,7 +267,7 @@ void Widget::CreateSlider(const QString& label, bool reversed, float multiplier,
|
||||||
if (Settings::IsConfiguringGlobal()) {
|
if (Settings::IsConfiguringGlobal()) {
|
||||||
load_func = [=]() { setting.LoadString(std::to_string(slider->value())); };
|
load_func = [=]() { setting.LoadString(std::to_string(slider->value())); };
|
||||||
} else {
|
} else {
|
||||||
restore_button = CreateRestoreGlobalButton(setting, this);
|
restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this);
|
||||||
layout->addWidget(restore_button);
|
layout->addWidget(restore_button);
|
||||||
|
|
||||||
QObject::connect(restore_button, &QAbstractButton::clicked, [=](bool) {
|
QObject::connect(restore_button, &QAbstractButton::clicked, [=](bool) {
|
||||||
|
@ -287,7 +293,7 @@ void Widget::CreateSlider(const QString& label, bool reversed, float multiplier,
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::CreateSpinBox(const QString& label, std::function<void()>& load_func, bool managed,
|
void Widget::CreateSpinBox(const QString& label, std::function<void()>& load_func, bool managed,
|
||||||
const std::string& suffix, Settings::BasicSetting* other_setting) {
|
const QString& suffix, Settings::BasicSetting* other_setting) {
|
||||||
const bool has_checkbox = other_setting != nullptr;
|
const bool has_checkbox = other_setting != nullptr;
|
||||||
if (has_checkbox && other_setting->TypeId() != typeid(bool)) {
|
if (has_checkbox && other_setting->TypeId() != typeid(bool)) {
|
||||||
LOG_WARNING(Frontend, "Extra setting requested but setting is not boolean");
|
LOG_WARNING(Frontend, "Extra setting requested but setting is not boolean");
|
||||||
|
@ -315,7 +321,7 @@ void Widget::CreateSpinBox(const QString& label, std::function<void()>& load_fun
|
||||||
spinbox = new QSpinBox(this);
|
spinbox = new QSpinBox(this);
|
||||||
spinbox->setRange(min_val, max_val);
|
spinbox->setRange(min_val, max_val);
|
||||||
spinbox->setValue(default_val);
|
spinbox->setValue(default_val);
|
||||||
spinbox->setSuffix(QString::fromStdString(suffix));
|
spinbox->setSuffix(suffix);
|
||||||
spinbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
spinbox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
|
|
||||||
layout->insertWidget(1, spinbox);
|
layout->insertWidget(1, spinbox);
|
||||||
|
@ -327,7 +333,8 @@ void Widget::CreateSpinBox(const QString& label, std::function<void()>& load_fun
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (!has_checkbox) {
|
if (!has_checkbox) {
|
||||||
restore_button = CreateRestoreGlobalButton(setting, this);
|
restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this);
|
||||||
|
layout->addWidget(restore_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject::connect(restore_button, &QAbstractButton::clicked,
|
QObject::connect(restore_button, &QAbstractButton::clicked,
|
||||||
|
@ -382,7 +389,7 @@ void Widget::CreateHexEdit(const QString& label, std::function<void()>& load_fun
|
||||||
setting.LoadString(hex_to_dec());
|
setting.LoadString(hex_to_dec());
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
restore_button = CreateRestoreGlobalButton(setting, this);
|
restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this);
|
||||||
layout->addWidget(restore_button);
|
layout->addWidget(restore_button);
|
||||||
|
|
||||||
QObject::connect(restore_button, &QAbstractButton::clicked, [=](bool) {
|
QObject::connect(restore_button, &QAbstractButton::clicked, [=](bool) {
|
||||||
|
@ -465,7 +472,7 @@ void Widget::CreateDateTimeEdit(const QString& label, std::function<void()>& loa
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (!has_checkbox) {
|
if (!has_checkbox) {
|
||||||
restore_button = CreateRestoreGlobalButton(setting, this);
|
restore_button = CreateRestoreGlobalButton(setting.UsingGlobal(), this);
|
||||||
layout->addWidget(restore_button);
|
layout->addWidget(restore_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,12 +522,12 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
|
||||||
apply_funcs{apply_funcs_} {}
|
apply_funcs{apply_funcs_} {}
|
||||||
|
|
||||||
Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translations_,
|
Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translations_,
|
||||||
QWidget* parent_, bool runtime_lock,
|
QWidget* parent_, bool runtime_lock_,
|
||||||
std::forward_list<std::function<void(bool)>>& apply_funcs_, RequestType request,
|
std::forward_list<std::function<void(bool)>>& apply_funcs_, RequestType request,
|
||||||
bool managed, float multiplier, Settings::BasicSetting* other_setting,
|
bool managed, float multiplier, Settings::BasicSetting* other_setting,
|
||||||
const std::string& string)
|
const QString& string)
|
||||||
: QWidget(parent_), parent{parent_}, translations{translations_}, setting{*setting_},
|
: QWidget(parent_), parent{parent_}, translations{translations_}, setting{*setting_},
|
||||||
apply_funcs{apply_funcs_} {
|
apply_funcs{apply_funcs_}, runtime_lock{runtime_lock_} {
|
||||||
if (!Settings::IsConfiguringGlobal() && !setting.Switchable()) {
|
if (!Settings::IsConfiguringGlobal() && !setting.Switchable()) {
|
||||||
LOG_DEBUG(Frontend, "\"{}\" is not switchable, skipping...", setting.GetLabel());
|
LOG_DEBUG(Frontend, "\"{}\" is not switchable, skipping...", setting.GetLabel());
|
||||||
return;
|
return;
|
||||||
|
@ -547,23 +554,16 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
|
||||||
std::function<void()> load_func = []() {};
|
std::function<void()> load_func = []() {};
|
||||||
|
|
||||||
if (type == typeid(bool)) {
|
if (type == typeid(bool)) {
|
||||||
switch (request) {
|
|
||||||
case RequestType::Default:
|
|
||||||
CreateCheckBox(&setting, label, load_func, managed);
|
CreateCheckBox(&setting, label, load_func, managed);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_WARNING(Frontend, "Requested widget is unimplemented.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (setting.IsEnum()) {
|
} else if (setting.IsEnum()) {
|
||||||
CreateCombobox(label, load_func, managed);
|
CreateCombobox(label, load_func, managed);
|
||||||
} else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) ||
|
} else if (type == typeid(u32) || type == typeid(int) || type == typeid(u16) ||
|
||||||
type == typeid(s64)) {
|
type == typeid(s64) || type == typeid(u8)) {
|
||||||
switch (request) {
|
switch (request) {
|
||||||
case RequestType::Slider:
|
case RequestType::Slider:
|
||||||
case RequestType::ReverseSlider:
|
case RequestType::ReverseSlider:
|
||||||
CreateSlider(label, request == RequestType::ReverseSlider, multiplier, load_func,
|
CreateSlider(label, request == RequestType::ReverseSlider, multiplier, load_func,
|
||||||
managed);
|
managed, string);
|
||||||
break;
|
break;
|
||||||
case RequestType::LineEdit:
|
case RequestType::LineEdit:
|
||||||
case RequestType::Default:
|
case RequestType::Default:
|
||||||
|
@ -586,7 +586,23 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (type == typeid(std::string)) {
|
} else if (type == typeid(std::string)) {
|
||||||
|
switch (request) {
|
||||||
|
case RequestType::Default:
|
||||||
|
case RequestType::LineEdit:
|
||||||
CreateLineEdit(label, load_func, managed);
|
CreateLineEdit(label, load_func, managed);
|
||||||
|
break;
|
||||||
|
case RequestType::ComboBox:
|
||||||
|
CreateCombobox(label, load_func, false);
|
||||||
|
break;
|
||||||
|
case RequestType::SpinBox:
|
||||||
|
case RequestType::Slider:
|
||||||
|
case RequestType::ReverseSlider:
|
||||||
|
case RequestType::HexEdit:
|
||||||
|
case RequestType::DateTimeEdit:
|
||||||
|
case RequestType::MaxEnum:
|
||||||
|
LOG_WARNING(Frontend, "Requested widget is unimplemented.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!created) {
|
if (!created) {
|
||||||
|
|
|
@ -38,15 +38,15 @@ public:
|
||||||
Widget(Settings::BasicSetting* setting, const TranslationMap& translations, QWidget* parent,
|
Widget(Settings::BasicSetting* setting, const TranslationMap& translations, QWidget* parent,
|
||||||
bool runtime_lock, std::forward_list<std::function<void(bool)>>& apply_funcs_,
|
bool runtime_lock, std::forward_list<std::function<void(bool)>>& apply_funcs_,
|
||||||
RequestType request = RequestType::Default, bool managed = true, float multiplier = 1.0f,
|
RequestType request = RequestType::Default, bool managed = true, float multiplier = 1.0f,
|
||||||
Settings::BasicSetting* other_setting = nullptr, const std::string& format = "");
|
Settings::BasicSetting* other_setting = nullptr,
|
||||||
|
const QString& string = QStringLiteral(""));
|
||||||
Widget(Settings::BasicSetting* setting_, const TranslationMap& translations_, QWidget* parent_,
|
Widget(Settings::BasicSetting* setting_, const TranslationMap& translations_, QWidget* parent_,
|
||||||
std::forward_list<std::function<void(bool)>>& apply_funcs_);
|
std::forward_list<std::function<void(bool)>>& apply_funcs_);
|
||||||
virtual ~Widget();
|
virtual ~Widget();
|
||||||
|
|
||||||
bool Valid();
|
bool Valid();
|
||||||
|
|
||||||
[[nodiscard]] static QPushButton* CreateRestoreGlobalButton(Settings::BasicSetting& setting,
|
[[nodiscard]] static QPushButton* CreateRestoreGlobalButton(bool using_global, QWidget* parent);
|
||||||
QWidget* parent);
|
|
||||||
|
|
||||||
QPushButton* restore_button{};
|
QPushButton* restore_button{};
|
||||||
QLineEdit* line_edit{};
|
QLineEdit* line_edit{};
|
||||||
|
@ -68,12 +68,12 @@ private:
|
||||||
void CreateHexEdit(const QString& label, std::function<void()>& load_func, bool managed,
|
void CreateHexEdit(const QString& label, std::function<void()>& load_func, bool managed,
|
||||||
Settings::BasicSetting* const other_setting = nullptr);
|
Settings::BasicSetting* const other_setting = nullptr);
|
||||||
void CreateSlider(const QString& label, bool reversed, float multiplier,
|
void CreateSlider(const QString& label, bool reversed, float multiplier,
|
||||||
std::function<void()>& load_func, bool managed,
|
std::function<void()>& load_func, bool managed, const QString& format,
|
||||||
Settings::BasicSetting* const other_setting = nullptr);
|
Settings::BasicSetting* const other_setting = nullptr);
|
||||||
void CreateDateTimeEdit(const QString& label, std::function<void()>& load_func, bool managed,
|
void CreateDateTimeEdit(const QString& label, std::function<void()>& load_func, bool managed,
|
||||||
bool restrict, Settings::BasicSetting* const other_setting = nullptr);
|
bool restrict, Settings::BasicSetting* const other_setting = nullptr);
|
||||||
void CreateSpinBox(const QString& label, std::function<void()>& load_func, bool managed,
|
void CreateSpinBox(const QString& label, std::function<void()>& load_func, bool managed,
|
||||||
const std::string& suffix, Settings::BasicSetting* other_setting = nullptr);
|
const QString& suffix, Settings::BasicSetting* other_setting = nullptr);
|
||||||
|
|
||||||
QWidget* parent;
|
QWidget* parent;
|
||||||
const TranslationMap& translations;
|
const TranslationMap& translations;
|
||||||
|
@ -81,6 +81,7 @@ private:
|
||||||
std::forward_list<std::function<void(bool)>>& apply_funcs;
|
std::forward_list<std::function<void(bool)>>& apply_funcs;
|
||||||
|
|
||||||
bool created{false};
|
bool created{false};
|
||||||
|
bool runtime_lock{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ConfigurationShared
|
} // namespace ConfigurationShared
|
||||||
|
|
Loading…
Reference in a new issue