mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-08 20:58:41 +00:00
Ds4 Speaker Audio Rebase Fix (#3607)
* Logic update, no QT ui * Fixing errors * Gui boxes * fixes * prevent device list refreshing too fast when game not running * Removed duplicate Socket declarations in kernel/file_system.cpp and fs.h * Fixed clang-format and micDevice errors * Ran clang-format and fixed rebase compiler issues * Settings dialog fix * Addressed squidbus' concerns * Update config.cpp to adhere to clang-format * Removed a space causing clang-format to complain * Addressed squidbus' concerns and added fallbacks Concerns: - Changed dev_name construct to remove unnecessary cast - Added an invalid AudioDeviceID macro to replace magic number --------- Co-authored-by: rainmakerv2 <30595646+rainmakerv3@users.noreply.github.com>
This commit is contained in:
@@ -136,10 +136,14 @@ static ConfigEntry<bool> useSpecialPad(false);
|
||||
static ConfigEntry<int> specialPadClass(1);
|
||||
static ConfigEntry<bool> isMotionControlsEnabled(true);
|
||||
static ConfigEntry<bool> useUnifiedInputConfig(true);
|
||||
static ConfigEntry<string> micDevice("Default Device");
|
||||
static ConfigEntry<string> defaultControllerID("");
|
||||
static ConfigEntry<bool> backgroundControllerInput(false);
|
||||
|
||||
// Audio
|
||||
static ConfigEntry<string> micDevice("Default Device");
|
||||
static ConfigEntry<string> mainOutputDevice("Default Device");
|
||||
static ConfigEntry<string> padSpkOutputDevice("Default Device");
|
||||
|
||||
// GPU
|
||||
static ConfigEntry<u32> windowWidth(1280);
|
||||
static ConfigEntry<u32> windowHeight(720);
|
||||
@@ -302,6 +306,14 @@ string getMicDevice() {
|
||||
return micDevice.get();
|
||||
}
|
||||
|
||||
std::string getMainOutputDevice() {
|
||||
return mainOutputDevice.get();
|
||||
}
|
||||
|
||||
std::string getPadSpkOutputDevice() {
|
||||
return padSpkOutputDevice.get();
|
||||
}
|
||||
|
||||
double getTrophyNotificationDuration() {
|
||||
return trophyNotificationDuration.get();
|
||||
}
|
||||
@@ -581,10 +593,18 @@ void setCursorHideTimeout(int newcursorHideTimeout, bool is_game_specific) {
|
||||
cursorHideTimeout.set(newcursorHideTimeout, is_game_specific);
|
||||
}
|
||||
|
||||
void setMicDevice(string device, bool is_game_specific) {
|
||||
void setMicDevice(std::string device, bool is_game_specific) {
|
||||
micDevice.set(device, is_game_specific);
|
||||
}
|
||||
|
||||
void setMainOutputDevice(std::string device, bool is_game_specific) {
|
||||
mainOutputDevice.set(device, is_game_specific);
|
||||
}
|
||||
|
||||
void setPadSpkOutputDevice(std::string device, bool is_game_specific) {
|
||||
padSpkOutputDevice.set(device, is_game_specific);
|
||||
}
|
||||
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration, bool is_game_specific) {
|
||||
trophyNotificationDuration.set(newTrophyNotificationDuration, is_game_specific);
|
||||
}
|
||||
@@ -826,10 +846,17 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
||||
specialPadClass.setFromToml(input, "specialPadClass", is_game_specific);
|
||||
isMotionControlsEnabled.setFromToml(input, "isMotionControlsEnabled", is_game_specific);
|
||||
useUnifiedInputConfig.setFromToml(input, "useUnifiedInputConfig", is_game_specific);
|
||||
micDevice.setFromToml(input, "micDevice", is_game_specific);
|
||||
backgroundControllerInput.setFromToml(input, "backgroundControllerInput", is_game_specific);
|
||||
}
|
||||
|
||||
if (data.contains("Audio")) {
|
||||
const toml::value& audio = data.at("Audio");
|
||||
|
||||
micDevice.setFromToml(audio, "micDevice", is_game_specific);
|
||||
mainOutputDevice.setFromToml(audio, "mainOutputDevice", is_game_specific);
|
||||
padSpkOutputDevice.setFromToml(audio, "padSpkOutputDevice", is_game_specific);
|
||||
}
|
||||
|
||||
if (data.contains("GPU")) {
|
||||
const toml::value& gpu = data.at("GPU");
|
||||
|
||||
@@ -999,10 +1026,13 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
||||
cursorHideTimeout.setTomlValue(data, "Input", "cursorHideTimeout", is_game_specific);
|
||||
isMotionControlsEnabled.setTomlValue(data, "Input", "isMotionControlsEnabled",
|
||||
is_game_specific);
|
||||
micDevice.setTomlValue(data, "Input", "micDevice", is_game_specific);
|
||||
backgroundControllerInput.setTomlValue(data, "Input", "backgroundControllerInput",
|
||||
is_game_specific);
|
||||
|
||||
micDevice.setTomlValue(data, "Audio", "micDevice", is_game_specific);
|
||||
mainOutputDevice.setTomlValue(data, "Audio", "mainOutputDevice", is_game_specific);
|
||||
padSpkOutputDevice.setTomlValue(data, "Audio", "padSpkOutputDevice", is_game_specific);
|
||||
|
||||
windowWidth.setTomlValue(data, "GPU", "screenWidth", is_game_specific);
|
||||
windowHeight.setTomlValue(data, "GPU", "screenHeight", is_game_specific);
|
||||
isNullGpu.setTomlValue(data, "GPU", "nullGpu", is_game_specific);
|
||||
@@ -1036,9 +1066,8 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
||||
|
||||
m_language.setTomlValue(data, "Settings", "consoleLanguage", is_game_specific);
|
||||
|
||||
// All other entries
|
||||
if (!is_game_specific) {
|
||||
std::vector<string> install_dirs;
|
||||
std::vector<std::string> install_dirs;
|
||||
std::vector<bool> install_dirs_enabled;
|
||||
|
||||
// temporary structure for ordering
|
||||
@@ -1077,23 +1106,18 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
||||
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
|
||||
data["GUI"]["addonInstallDir"] =
|
||||
string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
||||
|
||||
data["Debug"]["ConfigVersion"] = config_version;
|
||||
data["Keys"]["TrophyKey"] = trophyKey;
|
||||
|
||||
// Do not save these entries in the game-specific dialog since they are not in the GUI
|
||||
data["General"]["defaultControllerID"] = defaultControllerID.base_value;
|
||||
|
||||
data["Input"]["useSpecialPad"] = useSpecialPad.base_value;
|
||||
data["Input"]["specialPadClass"] = specialPadClass.base_value;
|
||||
data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig.base_value;
|
||||
|
||||
data["GPU"]["internalScreenWidth"] = internalScreenWidth.base_value;
|
||||
data["GPU"]["internalScreenHeight"] = internalScreenHeight.base_value;
|
||||
data["GPU"]["patchShaders"] = shouldPatchShaders.base_value;
|
||||
|
||||
data["Vulkan"]["validation_gpu"] = vkValidationGpu.base_value;
|
||||
|
||||
data["Debug"]["FPSColor"] = isFpsColor.base_value;
|
||||
}
|
||||
|
||||
@@ -1135,9 +1159,11 @@ void setDefaultValues(bool is_game_specific) {
|
||||
cursorState.set(HideCursorState::Idle, is_game_specific);
|
||||
cursorHideTimeout.set(5, is_game_specific);
|
||||
isMotionControlsEnabled.set(true, is_game_specific);
|
||||
micDevice.set("Default Device", is_game_specific);
|
||||
backgroundControllerInput.set(false, is_game_specific);
|
||||
|
||||
// GS - Audio
|
||||
micDevice.set("Default Device", is_game_specific);
|
||||
|
||||
// GS - GPU
|
||||
windowWidth.set(1280, is_game_specific);
|
||||
windowHeight.set(720, is_game_specific);
|
||||
@@ -1184,11 +1210,14 @@ void setDefaultValues(bool is_game_specific) {
|
||||
useSpecialPad.base_value = false;
|
||||
specialPadClass.base_value = 1;
|
||||
useUnifiedInputConfig.base_value = true;
|
||||
overrideControllerColor = false;
|
||||
controllerCustomColorRGB[0] = 0;
|
||||
controllerCustomColorRGB[1] = 0;
|
||||
controllerCustomColorRGB[2] = 255;
|
||||
|
||||
// TODO: Change to be game specific
|
||||
mainOutputDevice = "Default Device";
|
||||
padSpkOutputDevice = "Default Device";
|
||||
|
||||
// GPU
|
||||
shouldPatchShaders.base_value = false;
|
||||
internalScreenWidth.base_value = 1280;
|
||||
|
||||
@@ -90,6 +90,11 @@ double getTrophyNotificationDuration();
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration,
|
||||
bool is_game_specific = false);
|
||||
int getCursorHideTimeout();
|
||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||
std::string getMainOutputDevice();
|
||||
void setMainOutputDevice(std::string device);
|
||||
std::string getPadSpkOutputDevice();
|
||||
void setPadSpkOutputDevice(std::string device);
|
||||
std::string getMicDevice();
|
||||
void setCursorHideTimeout(int newcursorHideTimeout, bool is_game_specific = false);
|
||||
void setMicDevice(std::string device, bool is_game_specific = false);
|
||||
|
||||
@@ -208,7 +208,7 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta
|
||||
state->channel = port.format_info.num_channels > 2 ? 2 : port.format_info.num_channels;
|
||||
break;
|
||||
case OrbisAudioOutPort::Personal:
|
||||
case OrbisAudioOutPort::Padspk:
|
||||
case OrbisAudioOutPort::PadSpk:
|
||||
state->output = 4;
|
||||
state->channel = 1;
|
||||
break;
|
||||
@@ -328,7 +328,7 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
|
||||
LOG_ERROR(Lib_AudioOut, "Audio out not initialized");
|
||||
return ORBIS_AUDIO_OUT_ERROR_NOT_INIT;
|
||||
}
|
||||
if ((port_type < OrbisAudioOutPort::Main || port_type > OrbisAudioOutPort::Padspk) &&
|
||||
if ((port_type < OrbisAudioOutPort::Main || port_type > OrbisAudioOutPort::PadSpk) &&
|
||||
(port_type != OrbisAudioOutPort::Audio3d && port_type != OrbisAudioOutPort::Aux)) {
|
||||
LOG_ERROR(Lib_AudioOut, "Invalid port type");
|
||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT_TYPE;
|
||||
|
||||
@@ -25,7 +25,7 @@ enum class OrbisAudioOutPort {
|
||||
Bgm = 1,
|
||||
Voice = 2,
|
||||
Personal = 3,
|
||||
Padspk = 4,
|
||||
PadSpk = 4,
|
||||
Audio3d = 126,
|
||||
Aux = 127,
|
||||
};
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <SDL3/SDL_audio.h>
|
||||
#include <SDL3/SDL_hints.h>
|
||||
#include <common/config.h>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
#include "core/libraries/audio/audioout_backend.h"
|
||||
|
||||
#define SDL_INVALID_AUDIODEVICEID 0 // Defined in SDL_audio.h but not made a macro
|
||||
namespace Libraries::AudioOut {
|
||||
|
||||
class SDLPortBackend : public PortBackend {
|
||||
@@ -21,8 +23,42 @@ public:
|
||||
.channels = port.format_info.num_channels,
|
||||
.freq = static_cast<int>(port.sample_rate),
|
||||
};
|
||||
stream =
|
||||
SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &fmt, nullptr, nullptr);
|
||||
|
||||
// Determine port type
|
||||
std::string port_name = port.type == OrbisAudioOutPort::PadSpk
|
||||
? Config::getPadSpkOutputDevice()
|
||||
: Config::getMainOutputDevice();
|
||||
SDL_AudioDeviceID dev_id = SDL_INVALID_AUDIODEVICEID;
|
||||
if (port_name == "None") {
|
||||
stream = nullptr;
|
||||
return;
|
||||
} else if (port_name == "Default Device") {
|
||||
dev_id = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;
|
||||
} else {
|
||||
try {
|
||||
SDL_AudioDeviceID* dev_array = SDL_GetAudioPlaybackDevices(nullptr);
|
||||
for (; dev_array != 0;) {
|
||||
std::string dev_name(SDL_GetAudioDeviceName(*dev_array));
|
||||
if (dev_name == port_name) {
|
||||
dev_id = *dev_array;
|
||||
break;
|
||||
} else {
|
||||
dev_array++;
|
||||
}
|
||||
}
|
||||
if (dev_id == SDL_INVALID_AUDIODEVICEID) {
|
||||
LOG_WARNING(Lib_AudioOut, "Audio device not found: {}", port_name);
|
||||
dev_id = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR(Lib_AudioOut, "Invalid audio output device: {}", port_name);
|
||||
stream = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Open the audio stream
|
||||
stream = SDL_OpenAudioDeviceStream(dev_id, &fmt, nullptr, nullptr);
|
||||
if (stream == nullptr) {
|
||||
LOG_ERROR(Lib_AudioOut, "Failed to create SDL audio stream: {}", SDL_GetError());
|
||||
return;
|
||||
|
||||
@@ -408,8 +408,8 @@ public:
|
||||
}
|
||||
|
||||
if (selected == &gameConfigConfigure || selected == &gameConfigCreate) {
|
||||
auto settingsWindow = new SettingsDialog(m_gui_settings, m_compat_info, widget, true,
|
||||
serialStr.toStdString());
|
||||
auto settingsWindow = new SettingsDialog(m_gui_settings, m_compat_info, widget, false,
|
||||
true, serialStr.toStdString());
|
||||
settingsWindow->exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -407,7 +407,8 @@ void MainWindow::CreateConnects() {
|
||||
&MainWindow::StartGame);
|
||||
|
||||
connect(ui->configureAct, &QAction::triggered, this, [this]() {
|
||||
auto settingsDialog = new SettingsDialog(m_gui_settings, m_compat_info, this);
|
||||
auto settingsDialog =
|
||||
new SettingsDialog(m_gui_settings, m_compat_info, this, isGameRunning);
|
||||
|
||||
connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
|
||||
&MainWindow::OnLanguageChanged);
|
||||
@@ -441,7 +442,8 @@ void MainWindow::CreateConnects() {
|
||||
});
|
||||
|
||||
connect(ui->settingsButton, &QPushButton::clicked, this, [this]() {
|
||||
auto settingsDialog = new SettingsDialog(m_gui_settings, m_compat_info, this);
|
||||
auto settingsDialog =
|
||||
new SettingsDialog(m_gui_settings, m_compat_info, this, isGameRunning);
|
||||
|
||||
connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
|
||||
&MainWindow::OnLanguageChanged);
|
||||
|
||||
@@ -41,6 +41,14 @@ bool Wrapper::ProcessEvent(SDL_Event* event) {
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
emit SDLEvent(SDL_EVENT_GAMEPAD_AXIS_MOTION, event->gaxis.axis, event->gaxis.value);
|
||||
return true;
|
||||
case SDL_EVENT_AUDIO_DEVICE_ADDED:
|
||||
if (event->adevice.recording == 0)
|
||||
emit audioDeviceChanged(true);
|
||||
return true;
|
||||
case SDL_EVENT_AUDIO_DEVICE_REMOVED:
|
||||
if (event->adevice.recording == 0)
|
||||
emit audioDeviceChanged(false);
|
||||
return true;
|
||||
// block all other SDL events while wrapper is active
|
||||
default:
|
||||
return true;
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
|
||||
signals:
|
||||
void SDLEvent(int Type, int Input, int Value);
|
||||
void audioDeviceChanged(bool isAdd);
|
||||
};
|
||||
|
||||
} // namespace SdlEventWrapper
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/scm_rev.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
#include "qt_gui/compatibility_info.h"
|
||||
@@ -27,6 +28,7 @@
|
||||
#include "common/logging/backend.h"
|
||||
#include "common/logging/filter.h"
|
||||
#include "log_presets_dialog.h"
|
||||
#include "sdl_event_wrapper.h"
|
||||
#include "settings_dialog.h"
|
||||
#include "ui_settings_dialog.h"
|
||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||
@@ -82,18 +84,20 @@ static std::vector<QString> m_physical_devices;
|
||||
|
||||
SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
|
||||
QWidget* parent, bool is_game_specific, std::string gsc_serial)
|
||||
QWidget* parent, bool is_running, bool is_specific,
|
||||
std::string gsc_serial)
|
||||
: QDialog(parent), ui(new Ui::SettingsDialog), m_gui_settings(std::move(gui_settings)),
|
||||
game_specific(is_game_specific), gs_serial(gsc_serial) {
|
||||
is_game_running(is_running), is_game_specific(is_specific), gs_serial(gsc_serial) {
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->tabWidgetSettings->setUsesScrollButtons(false);
|
||||
|
||||
initialHeight = this->height();
|
||||
|
||||
// Add a small clear "x" button inside the Log Filter input
|
||||
ui->logFilterLineEdit->setClearButtonEnabled(true);
|
||||
|
||||
if (game_specific) {
|
||||
if (is_game_specific) {
|
||||
// Paths tab
|
||||
ui->tabWidgetSettings->setTabVisible(5, false);
|
||||
ui->chooseHomeTabComboBox->removeItem(5);
|
||||
@@ -109,7 +113,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
}
|
||||
|
||||
std::filesystem::path config_file =
|
||||
game_specific
|
||||
is_game_specific
|
||||
? Common::FS::GetUserPath(Common::FS::PathType::CustomConfigs) / (gs_serial + ".toml")
|
||||
: Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml";
|
||||
|
||||
@@ -184,6 +188,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
}
|
||||
|
||||
InitializeEmulatorLanguages();
|
||||
onAudioDeviceChange(true);
|
||||
LoadValuesFromConfig();
|
||||
|
||||
defaultTextEdit = tr("Point your mouse at an option to display its description.");
|
||||
@@ -194,17 +199,17 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this,
|
||||
[this, config_file](QAbstractButton* button) {
|
||||
if (button == ui->buttonBox->button(QDialogButtonBox::Save)) {
|
||||
is_saving = true;
|
||||
UpdateSettings(game_specific);
|
||||
Config::save(config_file, game_specific);
|
||||
is_game_saving = true;
|
||||
UpdateSettings(is_game_specific);
|
||||
Config::save(config_file, is_game_specific);
|
||||
QWidget::close();
|
||||
} else if (button == ui->buttonBox->button(QDialogButtonBox::Apply)) {
|
||||
UpdateSettings(game_specific);
|
||||
Config::save(config_file, game_specific);
|
||||
UpdateSettings(is_game_specific);
|
||||
Config::save(config_file, is_game_specific);
|
||||
} else if (button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)) {
|
||||
setDefaultValues();
|
||||
Config::setDefaultValues(game_specific);
|
||||
Config::save(config_file, game_specific);
|
||||
Config::setDefaultValues(is_game_specific);
|
||||
Config::save(config_file, is_game_specific);
|
||||
LoadValuesFromConfig();
|
||||
} else if (button == ui->buttonBox->button(QDialogButtonBox::Close)) {
|
||||
ui->backgroundImageOpacitySlider->setValue(backgroundImageOpacitySlider_backup);
|
||||
@@ -232,7 +237,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
{
|
||||
connect(ui->horizontalVolumeSlider, &QSlider::valueChanged, this, [this](int value) {
|
||||
VolumeSliderChange(value);
|
||||
Config::setVolumeSlider(value, game_specific);
|
||||
Config::setVolumeSlider(value, is_game_specific);
|
||||
Libraries::AudioOut::AdjustVol();
|
||||
});
|
||||
|
||||
@@ -526,30 +531,52 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
ui->networkConnectedCheckBox->installEventFilter(this);
|
||||
ui->psnSignInCheckBox->installEventFilter(this);
|
||||
}
|
||||
|
||||
SdlEventWrapper::Wrapper::wrapperActive = true;
|
||||
if (!is_game_running) {
|
||||
SDL_InitSubSystem(SDL_INIT_EVENTS);
|
||||
Polling = QtConcurrent::run(&SettingsDialog::pollSDLevents, this);
|
||||
} else {
|
||||
SdlEventWrapper::Wrapper* DeviceEventWrapper = SdlEventWrapper::Wrapper::GetInstance();
|
||||
QObject::connect(DeviceEventWrapper, &SdlEventWrapper::Wrapper::audioDeviceChanged, this,
|
||||
&SettingsDialog::onAudioDeviceChange);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::closeEvent(QCloseEvent* event) {
|
||||
if (!is_saving) {
|
||||
if (!is_game_saving) {
|
||||
ui->backgroundImageOpacitySlider->setValue(backgroundImageOpacitySlider_backup);
|
||||
emit BackgroundOpacityChanged(backgroundImageOpacitySlider_backup);
|
||||
ui->BGMVolumeSlider->setValue(bgm_volume_backup);
|
||||
BackgroundMusicPlayer::getInstance().setVolume(bgm_volume_backup);
|
||||
SyncRealTimeWidgetstoConfig();
|
||||
}
|
||||
|
||||
SdlEventWrapper::Wrapper::wrapperActive = false;
|
||||
if (!is_game_running) {
|
||||
SDL_Event quitLoop{};
|
||||
quitLoop.type = SDL_EVENT_QUIT;
|
||||
SDL_PushEvent(&quitLoop);
|
||||
Polling.waitForFinished();
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
SDL_Quit();
|
||||
}
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
|
||||
void SettingsDialog::LoadValuesFromConfig() {
|
||||
std::filesystem::path config_file;
|
||||
config_file =
|
||||
game_specific
|
||||
is_game_specific
|
||||
? Common::FS::GetUserPath(Common::FS::PathType::CustomConfigs) / (gs_serial + ".toml")
|
||||
: Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml";
|
||||
|
||||
std::error_code error;
|
||||
bool is_newly_created = false;
|
||||
if (!std::filesystem::exists(config_file, error)) {
|
||||
Config::save(config_file, game_specific);
|
||||
Config::save(config_file, is_game_specific);
|
||||
is_newly_created = true;
|
||||
}
|
||||
|
||||
@@ -567,7 +594,7 @@ void SettingsDialog::LoadValuesFromConfig() {
|
||||
15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 30, 28};
|
||||
|
||||
// Entries with no game-specific settings
|
||||
if (!game_specific) {
|
||||
if (!is_game_specific) {
|
||||
const auto save_data_path = Config::GetSaveDataPath();
|
||||
QString save_data_path_string;
|
||||
Common::FS::PathToQString(save_data_path_string, save_data_path);
|
||||
@@ -728,6 +755,11 @@ void SettingsDialog::LoadValuesFromConfig() {
|
||||
toml::find_or<bool>(data, "Debug", "CollectShader", false));
|
||||
ui->enableLoggingCheckBox->setChecked(toml::find_or<bool>(data, "Debug", "logEnabled", true));
|
||||
|
||||
ui->GenAudioComboBox->setCurrentText(QString::fromStdString(
|
||||
toml::find_or<std::string>(data, "General", "mainOutputDevice", "")));
|
||||
ui->DsAudioComboBox->setCurrentText(QString::fromStdString(
|
||||
toml::find_or<std::string>(data, "General", "padSpkOutputDevice", "")));
|
||||
|
||||
std::string chooseHomeTab =
|
||||
toml::find_or<std::string>(data, "General", "chooseHomeTab", "General");
|
||||
QString translatedText = chooseHomeTabMap.key(QString::fromStdString(chooseHomeTab));
|
||||
@@ -979,76 +1011,75 @@ bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) {
|
||||
return QDialog::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void SettingsDialog::UpdateSettings(bool game_specific) {
|
||||
void SettingsDialog::UpdateSettings(bool is_specific) {
|
||||
// Entries with game-specific settings, needs the game-specific arg
|
||||
Config::setReadbacks(ui->readbacksCheckBox->isChecked(), game_specific);
|
||||
Config::setReadbackLinearImages(ui->readbackLinearImagesCheckBox->isChecked(), game_specific);
|
||||
Config::setDirectMemoryAccess(ui->dmaCheckBox->isChecked(), game_specific);
|
||||
Config::setDevKitConsole(ui->devkitCheckBox->isChecked(), game_specific);
|
||||
Config::setNeoMode(ui->neoCheckBox->isChecked(), game_specific);
|
||||
Config::setConnectedToNetwork(ui->networkConnectedCheckBox->isChecked(), game_specific);
|
||||
Config::setPSNSignedIn(ui->psnSignInCheckBox->isChecked(), game_specific);
|
||||
Config::setReadbacks(ui->readbacksCheckBox->isChecked(), is_specific);
|
||||
Config::setReadbackLinearImages(ui->readbackLinearImagesCheckBox->isChecked(), is_specific);
|
||||
Config::setDirectMemoryAccess(ui->dmaCheckBox->isChecked(), is_specific);
|
||||
Config::setDevKitConsole(ui->devkitCheckBox->isChecked(), is_specific);
|
||||
Config::setNeoMode(ui->neoCheckBox->isChecked(), is_specific);
|
||||
Config::setConnectedToNetwork(ui->networkConnectedCheckBox->isChecked(), is_specific);
|
||||
Config::setPSNSignedIn(ui->psnSignInCheckBox->isChecked(), is_specific);
|
||||
|
||||
Config::setIsFullscreen(
|
||||
screenModeMap.value(ui->displayModeComboBox->currentText()) != "Windowed", game_specific);
|
||||
screenModeMap.value(ui->displayModeComboBox->currentText()) != "Windowed", is_specific);
|
||||
Config::setFullscreenMode(
|
||||
screenModeMap.value(ui->displayModeComboBox->currentText()).toStdString(), game_specific);
|
||||
screenModeMap.value(ui->displayModeComboBox->currentText()).toStdString(), is_specific);
|
||||
Config::setPresentMode(
|
||||
presentModeMap.value(ui->presentModeComboBox->currentText()).toStdString(), game_specific);
|
||||
Config::setIsMotionControlsEnabled(ui->motionControlsCheckBox->isChecked(), game_specific);
|
||||
presentModeMap.value(ui->presentModeComboBox->currentText()).toStdString(), is_specific);
|
||||
Config::setIsMotionControlsEnabled(ui->motionControlsCheckBox->isChecked(), is_specific);
|
||||
Config::setBackgroundControllerInput(ui->backgroundControllerCheckBox->isChecked(),
|
||||
game_specific);
|
||||
Config::setisTrophyPopupDisabled(ui->disableTrophycheckBox->isChecked(), game_specific);
|
||||
Config::setTrophyNotificationDuration(ui->popUpDurationSpinBox->value(), game_specific);
|
||||
is_specific);
|
||||
Config::setisTrophyPopupDisabled(ui->disableTrophycheckBox->isChecked(), is_specific);
|
||||
Config::setTrophyNotificationDuration(ui->popUpDurationSpinBox->value(), is_specific);
|
||||
|
||||
if (ui->radioButton_Top->isChecked()) {
|
||||
Config::setSideTrophy("top", game_specific);
|
||||
Config::setSideTrophy("top", is_specific);
|
||||
} else if (ui->radioButton_Left->isChecked()) {
|
||||
Config::setSideTrophy("left", game_specific);
|
||||
Config::setSideTrophy("left", is_specific);
|
||||
} else if (ui->radioButton_Right->isChecked()) {
|
||||
Config::setSideTrophy("right", game_specific);
|
||||
Config::setSideTrophy("right", is_specific);
|
||||
} else if (ui->radioButton_Bottom->isChecked()) {
|
||||
Config::setSideTrophy("bottom", game_specific);
|
||||
Config::setSideTrophy("bottom", is_specific);
|
||||
}
|
||||
|
||||
Config::setLoggingEnabled(ui->enableLoggingCheckBox->isChecked(), game_specific);
|
||||
Config::setAllowHDR(ui->enableHDRCheckBox->isChecked(), game_specific);
|
||||
Config::setLoggingEnabled(ui->enableLoggingCheckBox->isChecked(), is_specific);
|
||||
Config::setAllowHDR(ui->enableHDRCheckBox->isChecked(), is_specific);
|
||||
Config::setLogType(logTypeMap.value(ui->logTypeComboBox->currentText()).toStdString(),
|
||||
game_specific);
|
||||
Config::setMicDevice(ui->micComboBox->currentData().toString().toStdString(), game_specific);
|
||||
Config::setLogFilter(ui->logFilterLineEdit->text().toStdString(), game_specific);
|
||||
Config::setUserName(ui->userNameLineEdit->text().toStdString(), game_specific);
|
||||
Config::setCursorState(ui->hideCursorComboBox->currentIndex(), game_specific);
|
||||
Config::setCursorHideTimeout(ui->hideCursorComboBox->currentIndex(), game_specific);
|
||||
Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1, game_specific);
|
||||
Config::setVolumeSlider(ui->horizontalVolumeSlider->value(), game_specific);
|
||||
Config::setLanguage(languageIndexes[ui->consoleLanguageComboBox->currentIndex()],
|
||||
game_specific);
|
||||
Config::setWindowWidth(ui->widthSpinBox->value(), game_specific);
|
||||
Config::setWindowHeight(ui->heightSpinBox->value(), game_specific);
|
||||
Config::setVblankFreq(ui->vblankSpinBox->value(), game_specific);
|
||||
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked(), game_specific);
|
||||
Config::setNullGpu(ui->nullGpuCheckBox->isChecked(), game_specific);
|
||||
Config::setFsrEnabled(ui->FSRCheckBox->isChecked(), game_specific);
|
||||
Config::setRcasEnabled(ui->RCASCheckBox->isChecked(), game_specific);
|
||||
Config::setRcasAttenuation(ui->RCASSlider->value(), game_specific);
|
||||
Config::setShowSplash(ui->showSplashCheckBox->isChecked(), game_specific);
|
||||
Config::setDebugDump(ui->debugDump->isChecked(), game_specific);
|
||||
Config::setSeparateLogFilesEnabled(ui->separateLogFilesCheckbox->isChecked(), game_specific);
|
||||
Config::setVkValidation(ui->vkValidationCheckBox->isChecked(), game_specific);
|
||||
Config::setVkSyncValidation(ui->vkSyncValidationCheckBox->isChecked(), game_specific);
|
||||
Config::setRdocEnabled(ui->rdocCheckBox->isChecked(), game_specific);
|
||||
Config::setVkHostMarkersEnabled(ui->hostMarkersCheckBox->isChecked(), game_specific);
|
||||
Config::setVkGuestMarkersEnabled(ui->guestMarkersCheckBox->isChecked(), game_specific);
|
||||
Config::setVkCrashDiagnosticEnabled(ui->crashDiagnosticsCheckBox->isChecked(), game_specific);
|
||||
Config::setCollectShaderForDebug(ui->collectShaderCheckBox->isChecked(), game_specific);
|
||||
Config::setCopyGPUCmdBuffers(ui->copyGPUBuffersCheckBox->isChecked(), game_specific);
|
||||
is_specific);
|
||||
Config::setMicDevice(ui->micComboBox->currentData().toString().toStdString(), is_specific);
|
||||
Config::setLogFilter(ui->logFilterLineEdit->text().toStdString(), is_specific);
|
||||
Config::setUserName(ui->userNameLineEdit->text().toStdString(), is_specific);
|
||||
Config::setCursorState(ui->hideCursorComboBox->currentIndex(), is_specific);
|
||||
Config::setCursorHideTimeout(ui->hideCursorComboBox->currentIndex(), is_specific);
|
||||
Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1, is_specific);
|
||||
Config::setVolumeSlider(ui->horizontalVolumeSlider->value(), is_specific);
|
||||
Config::setLanguage(languageIndexes[ui->consoleLanguageComboBox->currentIndex()], is_specific);
|
||||
Config::setWindowWidth(ui->widthSpinBox->value(), is_specific);
|
||||
Config::setWindowHeight(ui->heightSpinBox->value(), is_specific);
|
||||
Config::setVblankFreq(ui->vblankSpinBox->value(), is_specific);
|
||||
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked(), is_specific);
|
||||
Config::setNullGpu(ui->nullGpuCheckBox->isChecked(), is_specific);
|
||||
Config::setFsrEnabled(ui->FSRCheckBox->isChecked(), is_specific);
|
||||
Config::setRcasEnabled(ui->RCASCheckBox->isChecked(), is_specific);
|
||||
Config::setRcasAttenuation(ui->RCASSlider->value(), is_specific);
|
||||
Config::setShowSplash(ui->showSplashCheckBox->isChecked(), is_specific);
|
||||
Config::setDebugDump(ui->debugDump->isChecked(), is_specific);
|
||||
Config::setSeparateLogFilesEnabled(ui->separateLogFilesCheckbox->isChecked(), is_specific);
|
||||
Config::setVkValidation(ui->vkValidationCheckBox->isChecked(), is_specific);
|
||||
Config::setVkSyncValidation(ui->vkSyncValidationCheckBox->isChecked(), is_specific);
|
||||
Config::setRdocEnabled(ui->rdocCheckBox->isChecked(), is_specific);
|
||||
Config::setVkHostMarkersEnabled(ui->hostMarkersCheckBox->isChecked(), is_specific);
|
||||
Config::setVkGuestMarkersEnabled(ui->guestMarkersCheckBox->isChecked(), is_specific);
|
||||
Config::setVkCrashDiagnosticEnabled(ui->crashDiagnosticsCheckBox->isChecked(), is_specific);
|
||||
Config::setCollectShaderForDebug(ui->collectShaderCheckBox->isChecked(), is_specific);
|
||||
Config::setCopyGPUCmdBuffers(ui->copyGPUBuffersCheckBox->isChecked(), is_specific);
|
||||
Config::setChooseHomeTab(
|
||||
chooseHomeTabMap.value(ui->chooseHomeTabComboBox->currentText()).toStdString(),
|
||||
game_specific);
|
||||
is_specific);
|
||||
|
||||
// Entries with no game-specific settings
|
||||
if (!game_specific) {
|
||||
if (!is_specific) {
|
||||
std::vector<Config::GameInstallDir> dirs_with_states;
|
||||
for (int i = 0; i < ui->gameFoldersListWidget->count(); i++) {
|
||||
QListWidgetItem* item = ui->gameFoldersListWidget->item(i);
|
||||
@@ -1096,7 +1127,7 @@ void SettingsDialog::SyncRealTimeWidgetstoConfig() {
|
||||
std::filesystem::path userdir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||
const toml::value data = toml::parse(userdir / "config.toml");
|
||||
|
||||
if (!game_specific) {
|
||||
if (!is_game_specific) {
|
||||
ui->gameFoldersListWidget->clear();
|
||||
if (data.contains("GUI")) {
|
||||
const toml::value& gui = data.at("GUI");
|
||||
@@ -1137,7 +1168,7 @@ void SettingsDialog::SyncRealTimeWidgetstoConfig() {
|
||||
}
|
||||
|
||||
toml::value gs_data;
|
||||
game_specific
|
||||
is_game_specific
|
||||
? gs_data = toml::parse(Common::FS::GetUserPath(Common::FS::PathType::CustomConfigs) /
|
||||
(gs_serial + ".toml"))
|
||||
: gs_data = data;
|
||||
@@ -1147,8 +1178,8 @@ void SettingsDialog::SyncRealTimeWidgetstoConfig() {
|
||||
|
||||
// Since config::set can be called for volume slider (connected to the widget) outside the save
|
||||
// function, need to null it out if GS GUI is closed without saving
|
||||
game_specific ? Config::resetGameSpecificValue("volumeSlider")
|
||||
: Config::setVolumeSlider(sliderValue);
|
||||
is_game_specific ? Config::resetGameSpecificValue("volumeSlider")
|
||||
: Config::setVolumeSlider(sliderValue);
|
||||
|
||||
if (presenter) {
|
||||
presenter->GetFsrSettingsRef().enable =
|
||||
@@ -1161,7 +1192,7 @@ void SettingsDialog::SyncRealTimeWidgetstoConfig() {
|
||||
}
|
||||
|
||||
void SettingsDialog::setDefaultValues() {
|
||||
if (!game_specific) {
|
||||
if (!is_game_specific) {
|
||||
m_gui_settings->SetValue(gui::gl_showBackgroundImage, true);
|
||||
m_gui_settings->SetValue(gui::gl_backgroundImageOpacity, 50);
|
||||
m_gui_settings->SetValue(gui::gl_playBackgroundMusic, false);
|
||||
@@ -1176,3 +1207,59 @@ void SettingsDialog::setDefaultValues() {
|
||||
m_gui_settings->SetValue(gui::gen_guiLanguage, "en_US");
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::pollSDLevents() {
|
||||
SDL_Event event;
|
||||
while (SdlEventWrapper::Wrapper::wrapperActive) {
|
||||
|
||||
if (!SDL_WaitEvent(&event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_AUDIO_DEVICE_ADDED) {
|
||||
onAudioDeviceChange(true);
|
||||
}
|
||||
|
||||
if (event.type == SDL_EVENT_AUDIO_DEVICE_REMOVED) {
|
||||
onAudioDeviceChange(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::onAudioDeviceChange(bool isAdd) {
|
||||
ui->GenAudioComboBox->clear();
|
||||
ui->DsAudioComboBox->clear();
|
||||
|
||||
// prevent device list from refreshing too fast when game not running
|
||||
if (!is_game_running && isAdd == false)
|
||||
QThread::msleep(100);
|
||||
|
||||
int deviceCount;
|
||||
QStringList deviceList;
|
||||
SDL_AudioDeviceID* devices = SDL_GetAudioPlaybackDevices(&deviceCount);
|
||||
|
||||
if (!devices) {
|
||||
LOG_ERROR(Lib_AudioOut, "Unable to retrieve audio device list {}", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < deviceCount; ++i) {
|
||||
const char* name = SDL_GetAudioDeviceName(devices[i]);
|
||||
std::string name_string = std::string(name);
|
||||
deviceList.append(QString::fromStdString(name_string));
|
||||
}
|
||||
|
||||
ui->GenAudioComboBox->addItem(tr("Default Device"), "Default Device");
|
||||
ui->GenAudioComboBox->addItems(deviceList);
|
||||
ui->GenAudioComboBox->setCurrentText(QString::fromStdString(Config::getMainOutputDevice()));
|
||||
|
||||
ui->DsAudioComboBox->addItem(tr("Default Device"), "Default Device");
|
||||
ui->DsAudioComboBox->addItems(deviceList);
|
||||
ui->DsAudioComboBox->setCurrentText(QString::fromStdString(Config::getPadSpkOutputDevice()));
|
||||
|
||||
SDL_free(devices);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ class SettingsDialog : public QDialog {
|
||||
public:
|
||||
explicit SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
|
||||
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
|
||||
QWidget* parent = nullptr, bool is_game_specific = false,
|
||||
std::string gsc_serial = "");
|
||||
QWidget* parent = nullptr, bool is_game_running = false,
|
||||
bool is_game_specific = false, std::string gsc_serial = "");
|
||||
~SettingsDialog();
|
||||
|
||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
@@ -47,6 +47,8 @@ private:
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
void setDefaultValues();
|
||||
void VolumeSliderChange(int value);
|
||||
void onAudioDeviceChange(bool isAdd);
|
||||
void pollSDLevents();
|
||||
|
||||
std::unique_ptr<Ui::SettingsDialog> ui;
|
||||
|
||||
@@ -55,9 +57,13 @@ private:
|
||||
QString defaultTextEdit;
|
||||
|
||||
int initialHeight;
|
||||
bool is_saving = false;
|
||||
bool game_specific;
|
||||
|
||||
std::string gs_serial;
|
||||
|
||||
bool is_game_running = false;
|
||||
bool is_game_specific = false;
|
||||
bool is_game_saving = false;
|
||||
|
||||
std::shared_ptr<gui_settings> m_gui_settings;
|
||||
QFuture<void> Polling;
|
||||
};
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>946</width>
|
||||
<height>501</height>
|
||||
<height>536</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="generalTabVLayout" stretch="0">
|
||||
@@ -381,6 +381,30 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="GenAudioGroupBox">
|
||||
<property name="title">
|
||||
<string>Audio Device (general)</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QComboBox" name="GenAudioComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="DsSpeakerGroupBox">
|
||||
<property name="title">
|
||||
<string>Audio Device (DS4 speaker)</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QComboBox" name="DsAudioComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1010,7 +1034,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>946</width>
|
||||
<height>501</height>
|
||||
<height>536</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="graphicsTabVLayout" stretch="0,0">
|
||||
@@ -1417,7 +1441,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>946</width>
|
||||
<height>501</height>
|
||||
<height>536</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="userTabVLayout" stretch="0,0,1">
|
||||
@@ -1632,7 +1656,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>946</width>
|
||||
<height>501</height>
|
||||
<height>536</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="inputTabVLayout" stretch="0,0,0">
|
||||
@@ -1918,7 +1942,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>946</width>
|
||||
<height>501</height>
|
||||
<height>536</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="pathsTabLayout">
|
||||
@@ -2087,7 +2111,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>946</width>
|
||||
<height>299</height>
|
||||
<height>536</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
||||
Reference in New Issue
Block a user