This commit is contained in:
georgemoralis 2025-07-22 08:28:10 +00:00 committed by GitHub
commit 402386a07e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 496 additions and 73 deletions

View File

@ -304,6 +304,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
src/core/libraries/audio/audioin.h src/core/libraries/audio/audioin.h
src/core/libraries/audio/sdl_in.h
src/core/libraries/audio/sdl_in.cpp
src/core/libraries/voice/voice.cpp src/core/libraries/voice/voice.cpp
src/core/libraries/voice/voice.h src/core/libraries/voice/voice.h
src/core/libraries/audio/audioout.cpp src/core/libraries/audio/audioout.cpp

View File

@ -55,6 +55,7 @@ static bool useSpecialPad = false;
static int specialPadClass = 1; static int specialPadClass = 1;
static bool isMotionControlsEnabled = true; static bool isMotionControlsEnabled = true;
static bool useUnifiedInputConfig = true; static bool useUnifiedInputConfig = true;
static std::string micDevice = "Default Device";
// These two entries aren't stored in the config // These two entries aren't stored in the config
static bool overrideControllerColor = false; static bool overrideControllerColor = false;
@ -201,6 +202,10 @@ int getCursorHideTimeout() {
return cursorHideTimeout; return cursorHideTimeout;
} }
std::string getMicDevice() {
return micDevice;
}
double getTrophyNotificationDuration() { double getTrophyNotificationDuration() {
return trophyNotificationDuration; return trophyNotificationDuration;
} }
@ -453,6 +458,10 @@ void setCursorHideTimeout(int newcursorHideTimeout) {
cursorHideTimeout = newcursorHideTimeout; cursorHideTimeout = newcursorHideTimeout;
} }
void setMicDevice(std::string device) {
micDevice = device;
}
void setTrophyNotificationDuration(double newTrophyNotificationDuration) { void setTrophyNotificationDuration(double newTrophyNotificationDuration) {
trophyNotificationDuration = newTrophyNotificationDuration; trophyNotificationDuration = newTrophyNotificationDuration;
} }
@ -652,6 +661,7 @@ void load(const std::filesystem::path& path) {
toml::find_or<bool>(input, "isMotionControlsEnabled", isMotionControlsEnabled); toml::find_or<bool>(input, "isMotionControlsEnabled", isMotionControlsEnabled);
useUnifiedInputConfig = useUnifiedInputConfig =
toml::find_or<bool>(input, "useUnifiedInputConfig", useUnifiedInputConfig); toml::find_or<bool>(input, "useUnifiedInputConfig", useUnifiedInputConfig);
micDevice = toml::find_or<std::string>(input, "micDevice", micDevice);
entry_count += input.size(); entry_count += input.size();
} }
@ -836,6 +846,7 @@ void save(const std::filesystem::path& path) {
data["Input"]["specialPadClass"] = specialPadClass; data["Input"]["specialPadClass"] = specialPadClass;
data["Input"]["isMotionControlsEnabled"] = isMotionControlsEnabled; data["Input"]["isMotionControlsEnabled"] = isMotionControlsEnabled;
data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig; data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig;
data["Input"]["micDevice"] = micDevice;
data["GPU"]["screenWidth"] = windowWidth; data["GPU"]["screenWidth"] = windowWidth;
data["GPU"]["screenHeight"] = windowHeight; data["GPU"]["screenHeight"] = windowHeight;
data["GPU"]["internalScreenWidth"] = internalScreenWidth; data["GPU"]["internalScreenWidth"] = internalScreenWidth;
@ -938,6 +949,7 @@ void setDefaultValues() {
controllerCustomColorRGB[0] = 0; controllerCustomColorRGB[0] = 0;
controllerCustomColorRGB[1] = 0; controllerCustomColorRGB[1] = 0;
controllerCustomColorRGB[2] = 255; controllerCustomColorRGB[2] = 255;
micDevice = "Default Device";
// GPU // GPU
windowWidth = 1280; windowWidth = 1280;

View File

@ -85,7 +85,9 @@ void setLogFilter(const std::string& type);
double getTrophyNotificationDuration(); double getTrophyNotificationDuration();
void setTrophyNotificationDuration(double newTrophyNotificationDuration); void setTrophyNotificationDuration(double newTrophyNotificationDuration);
int getCursorHideTimeout(); int getCursorHideTimeout();
std::string getMicDevice();
void setCursorHideTimeout(int newcursorHideTimeout); void setCursorHideTimeout(int newcursorHideTimeout);
void setMicDevice(std::string device);
void setSeparateLogFilesEnabled(bool enabled); void setSeparateLogFilesEnabled(bool enabled);
bool getSeparateLogFilesEnabled(); bool getSeparateLogFilesEnabled();
u32 GetLanguage(); u32 GetLanguage();

View File

@ -3,17 +3,21 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/audio/audioin.h" #include "core/libraries/audio/audioin.h"
#include "core/libraries/audio/sdl_in.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
namespace Libraries::AudioIn { namespace Libraries::AudioIn {
static std::unique_ptr<SDLAudioIn> audio = std::make_unique<SDLAudioIn>();
int PS4_SYSV_ABI sceAudioInChangeAppModuleState() { int PS4_SYSV_ABI sceAudioInChangeAppModuleState() {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInClose() { int PS4_SYSV_ABI sceAudioInClose(s32 handle) {
audio->AudioInClose(handle);
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); LOG_ERROR(Lib_AudioIn, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }
@ -93,9 +97,15 @@ int PS4_SYSV_ABI sceAudioInGetSilentState() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInHqOpen() { int PS4_SYSV_ABI sceAudioInHqOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); u32 index, u32 len, u32 freq, u32 param) {
return ORBIS_OK; LOG_ERROR(Lib_AudioIn, "called");
int result = audio->AudioInOpen(type, len, freq, param);
if (result == -1) {
LOG_ERROR(Lib_AudioOut, "Audio ports are full");
return 0x80260005;
}
return result;
} }
int PS4_SYSV_ABI sceAudioInHqOpenEx() { int PS4_SYSV_ABI sceAudioInHqOpenEx() {
@ -108,9 +118,8 @@ int PS4_SYSV_ABI sceAudioInInit() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInInput() { int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest) {
LOG_ERROR(Lib_AudioIn, "(STUBBED) called"); return audio->AudioInInput(handle, dest);
return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInInputs() { int PS4_SYSV_ABI sceAudioInInputs() {
@ -123,9 +132,15 @@ int PS4_SYSV_ABI sceAudioInIsSharedDevice() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceAudioInOpen() { int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
LOG_ERROR(Lib_AudioIn, "(DUMMY) called"); u32 index, u32 len, u32 freq, u32 param) {
return 0x80260005; // ports are full return LOG_ERROR(Lib_AudioIn, "called");
int result = audio->AudioInOpen(type, len, freq, param);
if (result == -1) {
LOG_ERROR(Lib_AudioOut, "Audio ports are full");
return 0x80260005;
}
return result;
} }
int PS4_SYSV_ABI sceAudioInOpenEx() { int PS4_SYSV_ABI sceAudioInOpenEx() {

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <core/libraries/system/userservice.h>
#include "common/types.h" #include "common/types.h"
namespace Core::Loader { namespace Core::Loader {
@ -11,8 +12,12 @@ class SymbolsResolver;
namespace Libraries::AudioIn { namespace Libraries::AudioIn {
enum class OrbisAudioInParamFormat : u32 { S16Mono = 0, S16Stereo = 2 };
enum class OrbisAudioInType : u32 { VoiceChat = 0, General = 1, VoiceRecognition = 5 };
int PS4_SYSV_ABI sceAudioInChangeAppModuleState(); int PS4_SYSV_ABI sceAudioInChangeAppModuleState();
int PS4_SYSV_ABI sceAudioInClose(); int PS4_SYSV_ABI sceAudioInClose(s32 handle);
int PS4_SYSV_ABI sceAudioInCountPorts(); int PS4_SYSV_ABI sceAudioInCountPorts();
int PS4_SYSV_ABI sceAudioInDeviceHqOpen(); int PS4_SYSV_ABI sceAudioInDeviceHqOpen();
int PS4_SYSV_ABI sceAudioInDeviceIdHqOpen(); int PS4_SYSV_ABI sceAudioInDeviceIdHqOpen();
@ -28,13 +33,15 @@ int PS4_SYSV_ABI sceAudioInGetGain();
int PS4_SYSV_ABI sceAudioInGetHandleStatusInfo(); int PS4_SYSV_ABI sceAudioInGetHandleStatusInfo();
int PS4_SYSV_ABI sceAudioInGetRerouteCount(); int PS4_SYSV_ABI sceAudioInGetRerouteCount();
int PS4_SYSV_ABI sceAudioInGetSilentState(); int PS4_SYSV_ABI sceAudioInGetSilentState();
int PS4_SYSV_ABI sceAudioInHqOpen(); int PS4_SYSV_ABI sceAudioInHqOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param);
int PS4_SYSV_ABI sceAudioInHqOpenEx(); int PS4_SYSV_ABI sceAudioInHqOpenEx();
int PS4_SYSV_ABI sceAudioInInit(); int PS4_SYSV_ABI sceAudioInInit();
int PS4_SYSV_ABI sceAudioInInput(); int PS4_SYSV_ABI sceAudioInInput(s32 handle, void* dest);
int PS4_SYSV_ABI sceAudioInInputs(); int PS4_SYSV_ABI sceAudioInInputs();
int PS4_SYSV_ABI sceAudioInIsSharedDevice(); int PS4_SYSV_ABI sceAudioInIsSharedDevice();
int PS4_SYSV_ABI sceAudioInOpen(); int PS4_SYSV_ABI sceAudioInOpen(Libraries::UserService::OrbisUserServiceUserId userId, u32 type,
u32 index, u32 len, u32 freq, u32 param);
int PS4_SYSV_ABI sceAudioInOpenEx(); int PS4_SYSV_ABI sceAudioInOpenEx();
int PS4_SYSV_ABI sceAudioInSetAllMute(); int PS4_SYSV_ABI sceAudioInSetAllMute();
int PS4_SYSV_ABI sceAudioInSetCompressorPreGain(); int PS4_SYSV_ABI sceAudioInSetCompressorPreGain();

View File

@ -0,0 +1,134 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
#include <common/config.h>
#include "sdl_in.h"
int SDLAudioIn::AudioInit() {
return SDL_InitSubSystem(SDL_INIT_AUDIO);
}
int SDLAudioIn::AudioInOpen(int type, uint32_t samples_num, uint32_t freq, uint32_t format) {
std::scoped_lock lock{m_mutex};
for (int id = 0; id < static_cast<int>(portsIn.size()); ++id) {
auto& port = portsIn[id];
if (!port.isOpen) {
port.isOpen = true;
port.type = type;
port.samples_num = samples_num;
port.freq = freq;
port.format = format;
SDL_AudioFormat sampleFormat;
switch (format) {
case Libraries::AudioIn::ORBIS_AUDIO_IN_PARAM_FORMAT_S16_MONO:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 1;
port.sample_size = 2;
break;
case Libraries::AudioIn::ORBIS_AUDIO_IN_PARAM_FORMAT_S16_STEREO:
sampleFormat = SDL_AUDIO_S16;
port.channels_num = 2;
port.sample_size = 2;
break;
default:
port.isOpen = false;
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
SDL_AudioSpec fmt;
SDL_zero(fmt);
fmt.format = sampleFormat;
fmt.channels = port.channels_num;
fmt.freq = port.freq;
std::string micDevStr = Config::getMicDevice();
uint32_t devId;
if (micDevStr == "None") {
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
} else if (micDevStr == "Default Device") {
devId = SDL_AUDIO_DEVICE_DEFAULT_RECORDING;
} else {
try {
devId = static_cast<uint32_t>(std::stoul(micDevStr));
} catch (const std::exception& e) {
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
}
port.stream = SDL_OpenAudioDeviceStream(devId, &fmt, nullptr, nullptr);
if (!port.stream) {
port.isOpen = false;
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
if (SDL_ResumeAudioStreamDevice(port.stream) == false) {
SDL_DestroyAudioStream(port.stream);
port = {};
return ORBIS_AUDIO_IN_ERROR_STREAM_FAIL;
}
return id + 1;
}
}
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
}
int SDLAudioIn::AudioInInput(int handle, void* out_buffer) {
std::scoped_lock lock{m_mutex};
if (handle < 1 || handle > static_cast<int>(portsIn.size()) || !out_buffer)
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
auto& port = portsIn[handle - 1];
if (!port.isOpen)
return ORBIS_AUDIO_IN_ERROR_INVALID_PORT;
const int bytesToRead = port.samples_num * port.sample_size * port.channels_num;
if (out_buffer == nullptr) {
int attempts = 0;
while (SDL_GetAudioStreamAvailable(port.stream) > 0) {
SDL_Delay(1);
if (++attempts > 1000) {
return ORBIS_AUDIO_IN_ERROR_TIMEOUT;
}
}
return 0; // done
}
int attempts = 0;
while (SDL_GetAudioStreamAvailable(port.stream) < bytesToRead) {
SDL_Delay(1);
if (++attempts > 1000) {
return ORBIS_AUDIO_IN_ERROR_TIMEOUT;
}
}
const int bytesRead = SDL_GetAudioStreamData(port.stream, out_buffer, bytesToRead);
if (bytesRead < 0) {
// SDL_GetAudioStreamData failed
SDL_Log("AudioInInput error: %s", SDL_GetError());
return ORBIS_AUDIO_IN_ERROR_STREAM_FAIL;
}
const int framesRead = bytesRead / (port.sample_size * port.channels_num);
return framesRead;
}
void SDLAudioIn::AudioInClose(int handle) {
std::scoped_lock lock{m_mutex};
if (handle < 1 || handle > (int)portsIn.size())
return;
auto& port = portsIn[handle - 1];
if (!port.isOpen)
return;
SDL_DestroyAudioStream(port.stream);
port = {};
}

View File

@ -0,0 +1,42 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <mutex>
#include <SDL3/SDL.h>
namespace Libraries::AudioIn {
enum OrbisAudioInParam {
ORBIS_AUDIO_IN_PARAM_FORMAT_S16_MONO = 0,
ORBIS_AUDIO_IN_PARAM_FORMAT_S16_STEREO = 2
};
}
#define ORBIS_AUDIO_IN_ERROR_INVALID_PORT -1
#define ORBIS_AUDIO_IN_ERROR_TIMEOUT -2
#define ORBIS_AUDIO_IN_ERROR_STREAM_FAIL -3
class SDLAudioIn {
public:
int AudioInit();
int AudioInOpen(int type, uint32_t samples_num, uint32_t freq, uint32_t format);
int AudioInInput(int handle, void* out_buffer);
void AudioInClose(int handle);
private:
struct AudioInPort {
bool isOpen = false;
int type = 0;
uint32_t samples_num = 0;
uint32_t freq = 0;
int channels_num = 0;
int sample_size = 0;
uint32_t format = 0;
SDL_AudioStream* stream = nullptr;
};
std::array<AudioInPort, 8> portsIn;
std::mutex m_mutex;
};

View File

@ -186,7 +186,7 @@ int PS4_SYSV_ABI sceHttpGetAcceptEncodingGZIPEnabled() {
int PS4_SYSV_ABI sceHttpGetAllResponseHeaders() { int PS4_SYSV_ABI sceHttpGetAllResponseHeaders() {
LOG_ERROR(Lib_Http, "(STUBBED) called"); LOG_ERROR(Lib_Http, "(STUBBED) called");
return ORBIS_OK; return ORBIS_FAIL;
} }
int PS4_SYSV_ABI sceHttpGetAuthEnabled() { int PS4_SYSV_ABI sceHttpGetAuthEnabled() {

View File

@ -7,6 +7,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QHoverEvent> #include <QHoverEvent>
#include <QMessageBox> #include <QMessageBox>
#include <SDL3/SDL.h>
#include <fmt/format.h> #include <fmt/format.h>
#include "common/config.h" #include "common/config.h"
@ -28,6 +29,7 @@
#include "settings_dialog.h" #include "settings_dialog.h"
#include "ui_settings_dialog.h" #include "ui_settings_dialog.h"
#include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_instance.h"
QStringList languageNames = {"Arabic", QStringList languageNames = {"Arabic",
"Czech", "Czech",
"Danish", "Danish",
@ -66,6 +68,7 @@ QMap<QString, QString> channelMap;
QMap<QString, QString> logTypeMap; QMap<QString, QString> logTypeMap;
QMap<QString, QString> screenModeMap; QMap<QString, QString> screenModeMap;
QMap<QString, QString> chooseHomeTabMap; QMap<QString, QString> chooseHomeTabMap;
QMap<QString, QString> micMap;
int backgroundImageOpacitySlider_backup; int backgroundImageOpacitySlider_backup;
int bgm_volume_backup; int bgm_volume_backup;
@ -94,6 +97,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
{tr("Graphics"), "Graphics"}, {tr("User"), "User"}, {tr("Graphics"), "Graphics"}, {tr("User"), "User"},
{tr("Input"), "Input"}, {tr("Paths"), "Paths"}, {tr("Input"), "Input"}, {tr("Paths"), "Paths"},
{tr("Debug"), "Debug"}}; {tr("Debug"), "Debug"}};
micMap = {{tr("None"), "None"}, {tr("Default Device"), "Default Device"}};
if (m_physical_devices.empty()) { if (m_physical_devices.empty()) {
// Populate cache of physical devices. // Populate cache of physical devices.
@ -125,6 +129,25 @@ SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
ui->hideCursorComboBox->addItem(tr("Idle")); ui->hideCursorComboBox->addItem(tr("Idle"));
ui->hideCursorComboBox->addItem(tr("Always")); ui->hideCursorComboBox->addItem(tr("Always"));
ui->micComboBox->addItem(micMap.key("None"), "None");
ui->micComboBox->addItem(micMap.key("Default Device"), "Default Device");
SDL_InitSubSystem(SDL_INIT_AUDIO);
int count = 0;
SDL_AudioDeviceID* devices = SDL_GetAudioRecordingDevices(&count);
if (devices) {
for (int i = 0; i < count; ++i) {
SDL_AudioDeviceID devId = devices[i];
const char* name = SDL_GetAudioDeviceName(devId);
if (name) {
QString qname = QString::fromUtf8(name);
ui->micComboBox->addItem(qname, QString::number(devId));
}
}
SDL_free(devices);
} else {
qDebug() << "Erro SDL_GetAudioRecordingDevices:" << SDL_GetError();
}
InitializeEmulatorLanguages(); InitializeEmulatorLanguages();
LoadValuesFromConfig(); LoadValuesFromConfig();
@ -453,6 +476,14 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->hideCursorComboBox->setCurrentIndex(toml::find_or<int>(data, "Input", "cursorState", 1)); ui->hideCursorComboBox->setCurrentIndex(toml::find_or<int>(data, "Input", "cursorState", 1));
OnCursorStateChanged(toml::find_or<int>(data, "Input", "cursorState", 1)); OnCursorStateChanged(toml::find_or<int>(data, "Input", "cursorState", 1));
ui->idleTimeoutSpinBox->setValue(toml::find_or<int>(data, "Input", "cursorHideTimeout", 5)); ui->idleTimeoutSpinBox->setValue(toml::find_or<int>(data, "Input", "cursorHideTimeout", 5));
QString micValue = QString::fromStdString(Config::getMicDevice());
int micIndex = ui->micComboBox->findData(micValue);
if (micIndex != -1) {
ui->micComboBox->setCurrentIndex(micIndex);
} else {
ui->micComboBox->setCurrentIndex(0);
}
// First options is auto selection -1, so gpuId on the GUI will always have to subtract 1 // First options is auto selection -1, so gpuId on the GUI will always have to subtract 1
// when setting and add 1 when getting to select the correct gpu in Qt // when setting and add 1 when getting to select the correct gpu in Qt
ui->graphicsAdapterBox->setCurrentIndex(toml::find_or<int>(data, "Vulkan", "gpuId", -1) + 1); ui->graphicsAdapterBox->setCurrentIndex(toml::find_or<int>(data, "Vulkan", "gpuId", -1) + 1);
@ -771,6 +802,7 @@ void SettingsDialog::UpdateSettings() {
m_gui_settings->SetValue(gui::gl_playBackgroundMusic, ui->playBGMCheckBox->isChecked()); m_gui_settings->SetValue(gui::gl_playBackgroundMusic, ui->playBGMCheckBox->isChecked());
Config::setAllowHDR(ui->enableHDRCheckBox->isChecked()); Config::setAllowHDR(ui->enableHDRCheckBox->isChecked());
Config::setLogType(logTypeMap.value(ui->logTypeComboBox->currentText()).toStdString()); Config::setLogType(logTypeMap.value(ui->logTypeComboBox->currentText()).toStdString());
Config::setMicDevice(ui->micComboBox->currentData().toString().toStdString());
Config::setLogFilter(ui->logFilterLineEdit->text().toStdString()); Config::setLogFilter(ui->logFilterLineEdit->text().toStdString());
Config::setUserName(ui->userNameLineEdit->text().toStdString()); Config::setUserName(ui->userNameLineEdit->text().toStdString());
Config::setTrophyKey(ui->trophyKeyLineEdit->text().toStdString()); Config::setTrophyKey(ui->trophyKeyLineEdit->text().toStdString());

View File

@ -86,7 +86,161 @@
<property name="spacing"> <property name="spacing">
<number>6</number> <number>6</number>
</property> </property>
<item row="2" column="0"> <item row="0" column="1">
<layout class="QVBoxLayout" name="emulatorTabLayoutMiddle">
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="emulatorSettingsGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Emulator</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="additionalSettingsVLayout" stretch="0">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<layout class="QVBoxLayout" name="emulatorverticalLayout">
<property name="spacing">
<number>10</number>
</property>
<item>
<widget class="QCheckBox" name="showSplashCheckBox">
<property name="text">
<string>Show Splash</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="discordRPCCheckbox">
<property name="text">
<string>Enable Discord Rich Presence</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_9">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="systemTabLayoutLeft">
<property name="spacing">
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="SystemSettings">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>System</string>
</property>
<layout class="QVBoxLayout" name="emuSettingsLayout">
<property name="bottomMargin">
<number>70</number>
</property>
<item>
<widget class="QGroupBox" name="consoleLanguageGroupBox">
<property name="title">
<string>Console Language</string>
</property>
<layout class="QVBoxLayout" name="settingsLayout">
<item>
<widget class="QComboBox" name="consoleLanguageComboBox"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="emulatorLanguageGroupBox">
<property name="title">
<string>Emulator Language</string>
</property>
<layout class="QVBoxLayout" name="langSettingsLayout">
<item>
<widget class="QComboBox" name="emulatorLanguageComboBox"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_3"> <spacer name="verticalSpacer_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Vertical</enum> <enum>Qt::Orientation::Vertical</enum>
@ -168,6 +322,32 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>80</number> <number>80</number>
</property> </property>
<item>
<widget class="QCheckBox" name="updateCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Check for Updates at Startup</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="changelogCheckBox">
<property name="text">
<string>Always Show Changelog</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="updaterComboBox"> <widget class="QGroupBox" name="updaterComboBox">
<property name="sizePolicy"> <property name="sizePolicy">
@ -255,32 +435,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="updateCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
<bold>false</bold>
</font>
</property>
<property name="text">
<string>Check for Updates at Startup</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="changelogCheckBox">
<property name="text">
<string>Always Show Changelog</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -1521,7 +1675,7 @@
<item> <item>
<layout class="QVBoxLayout" name="cursorTabLayoutLeft"> <layout class="QVBoxLayout" name="cursorTabLayoutLeft">
<property name="spacing"> <property name="spacing">
<number>7</number> <number>6</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
@ -1684,6 +1838,12 @@
<property name="title"> <property name="title">
<string>Controller</string> <string>Controller</string>
</property> </property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="ControllerLayout"> <layout class="QVBoxLayout" name="ControllerLayout">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
@ -1696,27 +1856,14 @@
</property> </property>
<item> <item>
<widget class="QCheckBox" name="motionControlsCheckBox"> <widget class="QCheckBox" name="motionControlsCheckBox">
<property name="text">
<string>Enable Motion Controls</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="controllerWidgetSpacer" native="true">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize"> <property name="text">
<size> <string>Enable Motion Controls</string>
<width>0</width>
<height>0</height>
</size>
</property> </property>
</widget> </widget>
</item> </item>
@ -1733,20 +1880,38 @@
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<spacer name="emptyVerticalSpacerBottom"> <layout class="QHBoxLayout" name="micTabLayoutLeft">
<property name="orientation"> <item>
<enum>Qt::Orientation::Vertical</enum> <widget class="QGroupBox" name="MicGroupBox">
</property> <property name="title">
<property name="sizeType"> <string>Microphone</string>
<enum>QSizePolicy::Policy::MinimumExpanding</enum> </property>
</property> <widget class="QComboBox" name="micComboBox">
<property name="sizeHint" stdset="0"> <property name="geometry">
<size> <rect>
<width>20</width> <x>14</x>
<height>20</height> <y>33</y>
</size> <width>431</width>
</property> <height>31</height>
</spacer> </rect>
</property>
</widget>
</widget>
</item>
<item>
<spacer name="verticalSpacer_8">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -1582,6 +1582,18 @@
<source>Hide Cursor Idle Timeout</source> <source>Hide Cursor Idle Timeout</source>
<translation>Hide Cursor Idle Timeout</translation> <translation>Hide Cursor Idle Timeout</translation>
</message> </message>
<message>
<source>Microphone</source>
<translation>Microphone</translation>
</message>
<message>
<source>None</source>
<translation>None</translation>
</message>
<message>
<source>Default Device</source>
<translation>Default Device</translation>
</message>
<message> <message>
<source>s</source> <source>s</source>
<translation>s</translation> <translation>s</translation>