configure_audio.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <memory>
  5. #include <QSignalBlocker>
  6. #include "audio_core/sink.h"
  7. #include "audio_core/sink_details.h"
  8. #include "common/settings.h"
  9. #include "core/core.h"
  10. #include "ui_configure_audio.h"
  11. #include "yuzu/configuration/configuration_shared.h"
  12. #include "yuzu/configuration/configure_audio.h"
  13. ConfigureAudio::ConfigureAudio(QWidget* parent)
  14. : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) {
  15. ui->setupUi(this);
  16. InitializeAudioOutputSinkComboBox();
  17. connect(ui->volume_slider, &QSlider::valueChanged, this,
  18. &ConfigureAudio::SetVolumeIndicatorText);
  19. connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
  20. &ConfigureAudio::UpdateAudioDevices);
  21. ui->volume_label->setVisible(Settings::IsConfiguringGlobal());
  22. ui->volume_combo_box->setVisible(!Settings::IsConfiguringGlobal());
  23. SetupPerGameUI();
  24. SetConfiguration();
  25. const bool is_powered_on = Core::System::GetInstance().IsPoweredOn();
  26. ui->output_sink_combo_box->setEnabled(!is_powered_on);
  27. ui->audio_device_combo_box->setEnabled(!is_powered_on);
  28. }
  29. ConfigureAudio::~ConfigureAudio() = default;
  30. void ConfigureAudio::SetConfiguration() {
  31. SetOutputSinkFromSinkID();
  32. // The device list cannot be pre-populated (nor listed) until the output sink is known.
  33. UpdateAudioDevices(ui->output_sink_combo_box->currentIndex());
  34. SetAudioDeviceFromDeviceID();
  35. ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum());
  36. ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue());
  37. if (!Settings::IsConfiguringGlobal()) {
  38. if (Settings::values.volume.UsingGlobal()) {
  39. ui->volume_combo_box->setCurrentIndex(0);
  40. ui->volume_slider->setEnabled(false);
  41. } else {
  42. ui->volume_combo_box->setCurrentIndex(1);
  43. ui->volume_slider->setEnabled(true);
  44. }
  45. ConfigurationShared::SetHighlight(ui->volume_layout,
  46. !Settings::values.volume.UsingGlobal());
  47. }
  48. SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
  49. }
  50. void ConfigureAudio::SetOutputSinkFromSinkID() {
  51. [[maybe_unused]] const QSignalBlocker blocker(ui->output_sink_combo_box);
  52. int new_sink_index = 0;
  53. const QString sink_id = QString::fromStdString(Settings::values.sink_id);
  54. for (int index = 0; index < ui->output_sink_combo_box->count(); index++) {
  55. if (ui->output_sink_combo_box->itemText(index) == sink_id) {
  56. new_sink_index = index;
  57. break;
  58. }
  59. }
  60. ui->output_sink_combo_box->setCurrentIndex(new_sink_index);
  61. }
  62. void ConfigureAudio::SetAudioDeviceFromDeviceID() {
  63. int new_device_index = -1;
  64. const QString device_id = QString::fromStdString(Settings::values.audio_device_id);
  65. for (int index = 0; index < ui->audio_device_combo_box->count(); index++) {
  66. if (ui->audio_device_combo_box->itemText(index) == device_id) {
  67. new_device_index = index;
  68. break;
  69. }
  70. }
  71. ui->audio_device_combo_box->setCurrentIndex(new_device_index);
  72. }
  73. void ConfigureAudio::SetVolumeIndicatorText(int percentage) {
  74. ui->volume_indicator->setText(tr("%1%", "Volume percentage (e.g. 50%)").arg(percentage));
  75. }
  76. void ConfigureAudio::ApplyConfiguration() {
  77. if (Settings::IsConfiguringGlobal()) {
  78. Settings::values.sink_id =
  79. ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex())
  80. .toStdString();
  81. Settings::values.audio_device_id =
  82. ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex())
  83. .toStdString();
  84. // Guard if during game and set to game-specific value
  85. if (Settings::values.enable_audio_stretching.UsingGlobal()) {
  86. Settings::values.enable_audio_stretching.SetValue(
  87. ui->toggle_audio_stretching->isChecked());
  88. }
  89. if (Settings::values.volume.UsingGlobal()) {
  90. Settings::values.volume.SetValue(
  91. static_cast<float>(ui->volume_slider->sliderPosition()) /
  92. ui->volume_slider->maximum());
  93. }
  94. } else {
  95. ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
  96. ui->toggle_audio_stretching,
  97. enable_audio_stretching);
  98. if (ui->volume_combo_box->currentIndex() == 0) {
  99. Settings::values.volume.SetGlobal(true);
  100. } else {
  101. Settings::values.volume.SetGlobal(false);
  102. Settings::values.volume.SetValue(
  103. static_cast<float>(ui->volume_slider->sliderPosition()) /
  104. ui->volume_slider->maximum());
  105. }
  106. }
  107. }
  108. void ConfigureAudio::changeEvent(QEvent* event) {
  109. if (event->type() == QEvent::LanguageChange) {
  110. RetranslateUI();
  111. }
  112. QWidget::changeEvent(event);
  113. }
  114. void ConfigureAudio::UpdateAudioDevices(int sink_index) {
  115. ui->audio_device_combo_box->clear();
  116. ui->audio_device_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
  117. const std::string sink_id = ui->output_sink_combo_box->itemText(sink_index).toStdString();
  118. for (const auto& device : AudioCore::GetDeviceListForSink(sink_id)) {
  119. ui->audio_device_combo_box->addItem(QString::fromStdString(device));
  120. }
  121. }
  122. void ConfigureAudio::InitializeAudioOutputSinkComboBox() {
  123. ui->output_sink_combo_box->clear();
  124. ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name));
  125. for (const char* id : AudioCore::GetSinkIDs()) {
  126. ui->output_sink_combo_box->addItem(QString::fromUtf8(id));
  127. }
  128. }
  129. void ConfigureAudio::RetranslateUI() {
  130. ui->retranslateUi(this);
  131. SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
  132. }
  133. void ConfigureAudio::SetupPerGameUI() {
  134. if (Settings::IsConfiguringGlobal()) {
  135. ui->volume_slider->setEnabled(Settings::values.volume.UsingGlobal());
  136. ui->toggle_audio_stretching->setEnabled(
  137. Settings::values.enable_audio_stretching.UsingGlobal());
  138. return;
  139. }
  140. ConfigurationShared::SetColoredTristate(ui->toggle_audio_stretching,
  141. Settings::values.enable_audio_stretching,
  142. enable_audio_stretching);
  143. connect(ui->volume_combo_box, qOverload<int>(&QComboBox::activated), this, [this](int index) {
  144. ui->volume_slider->setEnabled(index == 1);
  145. ConfigurationShared::SetHighlight(ui->volume_layout, index == 1);
  146. });
  147. ui->output_sink_combo_box->setVisible(false);
  148. ui->output_sink_label->setVisible(false);
  149. ui->audio_device_combo_box->setVisible(false);
  150. ui->audio_device_label->setVisible(false);
  151. }