diff options
| author | 2024-01-31 08:23:10 -0500 | |
|---|---|---|
| committer | 2024-01-31 09:31:19 -0500 | |
| commit | e8be665f1132503330137ecef352a2392f7f935c (patch) | |
| tree | 87d30a0cd88f6330b69de7c2de1fda6427860bd5 | |
| parent | Merge pull request #12856 from liamwhite/serialization (diff) | |
| download | yuzu-e8be665f1132503330137ecef352a2392f7f935c.tar.gz yuzu-e8be665f1132503330137ecef352a2392f7f935c.tar.xz yuzu-e8be665f1132503330137ecef352a2392f7f935c.zip | |
settings: Allow audio sink, input, and output to be set per game
| -rw-r--r-- | src/common/settings.h | 12 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_audio.cpp | 117 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_audio.h | 7 |
3 files changed, 110 insertions, 26 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index 16749ab68..f1b1add56 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -134,12 +134,12 @@ struct Values { | |||
| 134 | Linkage linkage{}; | 134 | Linkage linkage{}; |
| 135 | 135 | ||
| 136 | // Audio | 136 | // Audio |
| 137 | Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio, | 137 | SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", |
| 138 | Specialization::RuntimeList}; | 138 | Category::Audio, Specialization::RuntimeList}; |
| 139 | Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio, | 139 | SwitchableSetting<std::string> audio_output_device_id{ |
| 140 | Specialization::RuntimeList}; | 140 | linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList}; |
| 141 | Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio, | 141 | SwitchableSetting<std::string> audio_input_device_id{ |
| 142 | Specialization::RuntimeList}; | 142 | linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList}; |
| 143 | SwitchableSetting<AudioMode, true> sound_index{ | 143 | SwitchableSetting<AudioMode, true> sound_index{ |
| 144 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, | 144 | linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround, |
| 145 | "sound_index", Category::SystemAudio, Specialization::Default, true, | 145 | "sound_index", Category::SystemAudio, Specialization::Default, true, |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 9b6ef47a7..c235b0fca 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include <QComboBox> | 7 | #include <QComboBox> |
| 8 | #include <QPushButton> | ||
| 8 | 9 | ||
| 9 | #include "audio_core/sink/sink.h" | 10 | #include "audio_core/sink/sink.h" |
| 10 | #include "audio_core/sink/sink_details.h" | 11 | #include "audio_core/sink/sink_details.h" |
| @@ -67,19 +68,99 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 67 | 68 | ||
| 68 | hold.emplace(std::pair{setting->Id(), widget}); | 69 | hold.emplace(std::pair{setting->Id(), widget}); |
| 69 | 70 | ||
| 71 | auto global_sink_match = [this] { | ||
| 72 | return static_cast<Settings::AudioEngine>(sink_combo_box->currentIndex()) == | ||
| 73 | Settings::values.sink_id.GetValue(true); | ||
| 74 | }; | ||
| 70 | if (setting->Id() == Settings::values.sink_id.Id()) { | 75 | if (setting->Id() == Settings::values.sink_id.Id()) { |
| 71 | // TODO (lat9nq): Let the system manage sink_id | 76 | // TODO (lat9nq): Let the system manage sink_id |
| 72 | sink_combo_box = widget->combobox; | 77 | sink_combo_box = widget->combobox; |
| 73 | InitializeAudioSinkComboBox(); | 78 | InitializeAudioSinkComboBox(); |
| 74 | 79 | ||
| 75 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, | 80 | if (Settings::IsConfiguringGlobal()) { |
| 76 | &ConfigureAudio::UpdateAudioDevices); | 81 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| 82 | &ConfigureAudio::UpdateAudioDevices); | ||
| 83 | } else { | ||
| 84 | restore_sink_button = ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 85 | Settings::values.sink_id.UsingGlobal(), widget); | ||
| 86 | widget->layout()->addWidget(restore_sink_button); | ||
| 87 | connect(restore_sink_button, &QAbstractButton::clicked, [this](bool) { | ||
| 88 | Settings::values.sink_id.SetGlobal(true); | ||
| 89 | const int sink_index = static_cast<int>(Settings::values.sink_id.GetValue()); | ||
| 90 | sink_combo_box->setCurrentIndex(sink_index); | ||
| 91 | ConfigureAudio::UpdateAudioDevices(sink_index); | ||
| 92 | Settings::values.audio_output_device_id.SetGlobal(true); | ||
| 93 | Settings::values.audio_input_device_id.SetGlobal(true); | ||
| 94 | restore_sink_button->setVisible(false); | ||
| 95 | }); | ||
| 96 | connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 97 | [this, global_sink_match](const int slot) { | ||
| 98 | Settings::values.sink_id.SetGlobal(false); | ||
| 99 | Settings::values.audio_output_device_id.SetGlobal(false); | ||
| 100 | Settings::values.audio_input_device_id.SetGlobal(false); | ||
| 101 | |||
| 102 | restore_sink_button->setVisible(true); | ||
| 103 | restore_sink_button->setEnabled(true); | ||
| 104 | output_device_combo_box->setCurrentIndex(0); | ||
| 105 | restore_output_device_button->setVisible(true); | ||
| 106 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 107 | input_device_combo_box->setCurrentIndex(0); | ||
| 108 | restore_input_device_button->setVisible(true); | ||
| 109 | restore_input_device_button->setEnabled(global_sink_match()); | ||
| 110 | ConfigureAudio::UpdateAudioDevices(slot); | ||
| 111 | }); | ||
| 112 | } | ||
| 77 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { | 113 | } else if (setting->Id() == Settings::values.audio_output_device_id.Id()) { |
| 78 | // Keep track of output (and input) device comboboxes to populate them with system | 114 | // Keep track of output (and input) device comboboxes to populate them with system |
| 79 | // devices, which are determined at run time | 115 | // devices, which are determined at run time |
| 80 | output_device_combo_box = widget->combobox; | 116 | output_device_combo_box = widget->combobox; |
| 117 | |||
| 118 | if (!Settings::IsConfiguringGlobal()) { | ||
| 119 | restore_output_device_button = | ||
| 120 | ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 121 | Settings::values.audio_output_device_id.UsingGlobal(), widget); | ||
| 122 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 123 | restore_output_device_button->setVisible( | ||
| 124 | !Settings::values.audio_output_device_id.UsingGlobal()); | ||
| 125 | widget->layout()->addWidget(restore_output_device_button); | ||
| 126 | connect(restore_output_device_button, &QAbstractButton::clicked, [this](bool) { | ||
| 127 | Settings::values.audio_output_device_id.SetGlobal(true); | ||
| 128 | SetOutputDevicesFromDeviceID(); | ||
| 129 | restore_output_device_button->setVisible(false); | ||
| 130 | }); | ||
| 131 | connect(output_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 132 | [this, global_sink_match](int) { | ||
| 133 | if (updating_devices) { | ||
| 134 | return; | ||
| 135 | } | ||
| 136 | Settings::values.audio_output_device_id.SetGlobal(false); | ||
| 137 | restore_output_device_button->setVisible(true); | ||
| 138 | restore_output_device_button->setEnabled(global_sink_match()); | ||
| 139 | }); | ||
| 140 | } | ||
| 81 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { | 141 | } else if (setting->Id() == Settings::values.audio_input_device_id.Id()) { |
| 82 | input_device_combo_box = widget->combobox; | 142 | input_device_combo_box = widget->combobox; |
| 143 | |||
| 144 | if (!Settings::IsConfiguringGlobal()) { | ||
| 145 | restore_input_device_button = | ||
| 146 | ConfigurationShared::Widget::CreateRestoreGlobalButton( | ||
| 147 | Settings::values.audio_input_device_id.UsingGlobal(), widget); | ||
| 148 | widget->layout()->addWidget(restore_input_device_button); | ||
| 149 | connect(restore_input_device_button, &QAbstractButton::clicked, [this](bool) { | ||
| 150 | Settings::values.audio_input_device_id.SetGlobal(true); | ||
| 151 | SetInputDevicesFromDeviceID(); | ||
| 152 | restore_input_device_button->setVisible(false); | ||
| 153 | }); | ||
| 154 | connect(input_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), | ||
| 155 | [this, global_sink_match](int) { | ||
| 156 | if (updating_devices) { | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | Settings::values.audio_input_device_id.SetGlobal(false); | ||
| 160 | restore_input_device_button->setVisible(true); | ||
| 161 | restore_input_device_button->setEnabled(global_sink_match()); | ||
| 162 | }); | ||
| 163 | } | ||
| 83 | } | 164 | } |
| 84 | } | 165 | } |
| 85 | 166 | ||
| @@ -89,16 +170,13 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { | |||
| 89 | } | 170 | } |
| 90 | 171 | ||
| 91 | void ConfigureAudio::SetConfiguration() { | 172 | void ConfigureAudio::SetConfiguration() { |
| 92 | if (!Settings::IsConfiguringGlobal()) { | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | |||
| 96 | SetOutputSinkFromSinkID(); | 173 | SetOutputSinkFromSinkID(); |
| 97 | 174 | ||
| 98 | // The device list cannot be pre-populated (nor listed) until the output sink is known. | 175 | // The device list cannot be pre-populated (nor listed) until the output sink is known. |
| 99 | UpdateAudioDevices(sink_combo_box->currentIndex()); | 176 | UpdateAudioDevices(sink_combo_box->currentIndex()); |
| 100 | 177 | ||
| 101 | SetAudioDevicesFromDeviceID(); | 178 | SetOutputDevicesFromDeviceID(); |
| 179 | SetInputDevicesFromDeviceID(); | ||
| 102 | } | 180 | } |
| 103 | 181 | ||
| 104 | void ConfigureAudio::SetOutputSinkFromSinkID() { | 182 | void ConfigureAudio::SetOutputSinkFromSinkID() { |
| @@ -116,8 +194,8 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | |||
| 116 | sink_combo_box->setCurrentIndex(new_sink_index); | 194 | sink_combo_box->setCurrentIndex(new_sink_index); |
| 117 | } | 195 | } |
| 118 | 196 | ||
| 119 | void ConfigureAudio::SetAudioDevicesFromDeviceID() { | 197 | void ConfigureAudio::SetOutputDevicesFromDeviceID() { |
| 120 | int new_device_index = -1; | 198 | int new_device_index = 0; |
| 121 | 199 | ||
| 122 | const QString output_device_id = | 200 | const QString output_device_id = |
| 123 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); | 201 | QString::fromStdString(Settings::values.audio_output_device_id.GetValue()); |
| @@ -129,8 +207,10 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() { | |||
| 129 | } | 207 | } |
| 130 | 208 | ||
| 131 | output_device_combo_box->setCurrentIndex(new_device_index); | 209 | output_device_combo_box->setCurrentIndex(new_device_index); |
| 210 | } | ||
| 132 | 211 | ||
| 133 | new_device_index = -1; | 212 | void ConfigureAudio::SetInputDevicesFromDeviceID() { |
| 213 | int new_device_index = 0; | ||
| 134 | const QString input_device_id = | 214 | const QString input_device_id = |
| 135 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); | 215 | QString::fromStdString(Settings::values.audio_input_device_id.GetValue()); |
| 136 | for (int index = 0; index < input_device_combo_box->count(); index++) { | 216 | for (int index = 0; index < input_device_combo_box->count(); index++) { |
| @@ -149,15 +229,12 @@ void ConfigureAudio::ApplyConfiguration() { | |||
| 149 | apply_func(is_powered_on); | 229 | apply_func(is_powered_on); |
| 150 | } | 230 | } |
| 151 | 231 | ||
| 152 | if (Settings::IsConfiguringGlobal()) { | 232 | Settings::values.sink_id.LoadString( |
| 153 | Settings::values.sink_id.LoadString( | 233 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); |
| 154 | sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString()); | 234 | Settings::values.audio_output_device_id.SetValue( |
| 155 | Settings::values.audio_output_device_id.SetValue( | 235 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString()); |
| 156 | output_device_combo_box->itemText(output_device_combo_box->currentIndex()) | 236 | Settings::values.audio_input_device_id.SetValue( |
| 157 | .toStdString()); | 237 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); |
| 158 | Settings::values.audio_input_device_id.SetValue( | ||
| 159 | input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString()); | ||
| 160 | } | ||
| 161 | } | 238 | } |
| 162 | 239 | ||
| 163 | void ConfigureAudio::changeEvent(QEvent* event) { | 240 | void ConfigureAudio::changeEvent(QEvent* event) { |
| @@ -169,6 +246,7 @@ void ConfigureAudio::changeEvent(QEvent* event) { | |||
| 169 | } | 246 | } |
| 170 | 247 | ||
| 171 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { | 248 | void ConfigureAudio::UpdateAudioDevices(int sink_index) { |
| 249 | updating_devices = true; | ||
| 172 | output_device_combo_box->clear(); | 250 | output_device_combo_box->clear(); |
| 173 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); | 251 | output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name)); |
| 174 | 252 | ||
| @@ -183,6 +261,7 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) { | |||
| 183 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { | 261 | for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) { |
| 184 | input_device_combo_box->addItem(QString::fromStdString(device)); | 262 | input_device_combo_box->addItem(QString::fromStdString(device)); |
| 185 | } | 263 | } |
| 264 | updating_devices = false; | ||
| 186 | } | 265 | } |
| 187 | 266 | ||
| 188 | void ConfigureAudio::InitializeAudioSinkComboBox() { | 267 | void ConfigureAudio::InitializeAudioSinkComboBox() { |
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 82d7f6524..32a2fa5f0 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h | |||
| @@ -45,7 +45,8 @@ private: | |||
| 45 | void UpdateAudioDevices(int sink_index); | 45 | void UpdateAudioDevices(int sink_index); |
| 46 | 46 | ||
| 47 | void SetOutputSinkFromSinkID(); | 47 | void SetOutputSinkFromSinkID(); |
| 48 | void SetAudioDevicesFromDeviceID(); | 48 | void SetOutputDevicesFromDeviceID(); |
| 49 | void SetInputDevicesFromDeviceID(); | ||
| 49 | 50 | ||
| 50 | void Setup(const ConfigurationShared::Builder& builder); | 51 | void Setup(const ConfigurationShared::Builder& builder); |
| 51 | 52 | ||
| @@ -55,7 +56,11 @@ private: | |||
| 55 | 56 | ||
| 56 | std::vector<std::function<void(bool)>> apply_funcs{}; | 57 | std::vector<std::function<void(bool)>> apply_funcs{}; |
| 57 | 58 | ||
| 59 | bool updating_devices = false; | ||
| 58 | QComboBox* sink_combo_box; | 60 | QComboBox* sink_combo_box; |
| 61 | QPushButton* restore_sink_button; | ||
| 59 | QComboBox* output_device_combo_box; | 62 | QComboBox* output_device_combo_box; |
| 63 | QPushButton* restore_output_device_button; | ||
| 60 | QComboBox* input_device_combo_box; | 64 | QComboBox* input_device_combo_box; |
| 65 | QPushButton* restore_input_device_button; | ||
| 61 | }; | 66 | }; |