be able to configure audioOutputEngine

This commit is contained in:
N3xoX1 2025-06-29 08:29:03 +09:30
parent 5aed642d77
commit 00bd756d28
40 changed files with 584 additions and 130 deletions

View File

@ -0,0 +1,17 @@
{
"Core" : {
"ModuleDirectory-x64" : "..\\..\\..\\modules\\x64",
"ShowConsole" : true,
"modules" : {
"loader" : "loader\\yuzu-loader_d.dll"
}
},
"UI" : {
"EnableModuleConfiguration" : true,
"LanguageDirectory" : "..\\..\\..\\lang",
"RecentFiles" : [
"D:\\Emulation\\switch\\Games\\Sonic Mania.xci",
"D:\\Emulation\\switch\\Games\\2048.nro"
]
}
}

2
external/sciterui vendored

@ -1 +1 @@
Subproject commit 4caaf3d3bbfe54f832b3f95fc01e15996fbbf002
Subproject commit ae65e10d1067a44f91448e8726fea91db1dcc853

View File

@ -94,6 +94,11 @@ slider {
style-set: std-hslider;
}
ComboBox
{
width: 100%%;
}
@set std-hslider < std-hslider-base {
:root {
background: #565a5e;
@ -146,6 +151,7 @@ input[type="checkbox"] {
border: 1px solid #818183;
background: none;
border-radius: 0.3em;
margin: 0 0.5em 0 0;
}
input[type="checkbox"]:checked {
@ -169,7 +175,7 @@ input[type="checkbox"]:checked {
<div id="ConfigContents" />
</div>
<div class="footer">
<button role="window-close">OK</button>
<button role="window-ok">OK</button>
<button role="window-close">Cancel</button>
</div>
</body>

View File

@ -2,19 +2,19 @@
<div class="group-title">Audio</div>
<div class="form-row">
<div class="left"><label for="audioOutputEngine">Output Engine:</label></div>
<div class="right"><select id="audioOutputEngine"></select></div>
<div class="right"><ComboBox id="audioOutputEngine" /></div>
</div>
<div class="form-row">
<div class="left"><label for="audioOutputDevice">Output Device:</label></div>
<div class="right"><select id="audioOutputDevice"></select></div>
<div class="right"><ComboBox id="audioOutputDevice" /></div>
</div>
<div class="form-row">
<div class="left"><label for="inputDevice">Input Device:</label></div>
<div class="right"><select id="inputDevice"></select></div>
<div class="right"><ComboBox id="inputDevice" /></div>
</div>
<div class="form-row">
<div class="left"><label for="soundMode">Sound Output Mode:</label></div>
<div class="right"><select id="soundMode"></select></div>
<div class="right"><ComboBox id="soundMode" /></div>
</div>
<div class="form-row slider-row">
<div class="left"><label for="volume">Volume:</label></div>

View File

@ -9,7 +9,7 @@ extern "C" int __stdcall AllocConsole();
bool AppInit(INotification * notification)
{
g_notify = notification;
if (!Settings::GetInstance().Initialize())
if (!SettingsStore::GetInstance().Initialize())
{
return false;
}
@ -35,5 +35,5 @@ bool AppInit(INotification * notification)
void AppCleanup(void)
{
SwitchSystem::ShutDown();
Settings::CleanUp();
SettingsStore::CleanUp();
}

View File

@ -52,7 +52,7 @@ bool SwitchSystem::Initialize(IRenderWindow & window)
void SwitchSystem::StartEmulation(void)
{
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
settings.SetBool(NXCoreSetting::EmulationRunning, true);
m_emulationRunning = true;
m_modules.StartEmulation();
@ -68,6 +68,11 @@ void SwitchSystem::StopEmulation(void)
m_modules.StopEmulation();
}
void SwitchSystem::FlushSettings(void)
{
m_modules.FlushSettings();
}
IVideo & SwitchSystem::Video(void)
{
return *m_modules.Video();

View File

@ -14,6 +14,7 @@ public:
void StartEmulation(void);
void StopEmulation(void);
void FlushSettings(void);
//ISwitchSystem
ISystemloader & Systemloader();

View File

@ -5,7 +5,8 @@ ModuleBase::ModuleBase() :
m_moduleInfo({0}),
EmulationStarting(nullptr),
EmulationStopping(nullptr),
ModuleCleanup(nullptr)
ModuleCleanup(nullptr),
FlushSettings(nullptr)
{
}
@ -43,11 +44,13 @@ bool ModuleBase::Load(const char * fileName, IModuleNotification * notification,
ModuleCleanup = (ModuleBase::tyModuleCleanup)DynamicLibraryGetProc(m_lib, "ModuleCleanup");
EmulationStarting = (ModuleBase::tyEmulationStarting)DynamicLibraryGetProc(m_lib, "EmulationStarting");
EmulationStopping = (ModuleBase::tyEmulationStopping)DynamicLibraryGetProc(m_lib, "EmulationStopping");
FlushSettings = (ModuleBase::tyFlushSettings)DynamicLibraryGetProc(m_lib, "FlushSettings");
if (ModuleInitialize == nullptr ||
ModuleCleanup == nullptr ||
EmulationStarting == nullptr ||
EmulationStopping == nullptr)
EmulationStopping == nullptr ||
FlushSettings == nullptr)
{
return false;
}
@ -107,4 +110,5 @@ void ModuleBase::ModuleDone(bool callUnloadModule)
ModuleCleanup = nullptr;
EmulationStarting = nullptr;
EmulationStopping = nullptr;
FlushSettings = nullptr;
}

View File

@ -17,6 +17,7 @@ class ModuleBase
typedef void(CALL * tyModuleCleanup)();
typedef void(CALL * tyEmulationStarting)();
typedef void(CALL * tyEmulationStopping)();
typedef void(CALL * tyFlushSettings)();
public:
ModuleBase();
@ -26,6 +27,7 @@ public:
ModuleBase::tyEmulationStarting EmulationStarting;
ModuleBase::tyEmulationStopping EmulationStopping;
ModuleBase::tyModuleCleanup ModuleCleanup;
ModuleBase::tyFlushSettings FlushSettings;
protected:
virtual void UnloadModule(void) = 0;

View File

@ -1,22 +1,80 @@
#include "module_settings.h"
#include "settings/settings.h"
std::string ModuleSettings::GetString(const char * setting) const
const char * ModuleSettings::GetString(const char * setting) const
{
return Settings::GetInstance().GetString(setting);
return SettingsStore::GetInstance().GetString(setting);
}
bool ModuleSettings::GetBool(const char * setting) const
{
return Settings::GetInstance().GetBool(setting);
return SettingsStore::GetInstance().GetBool(setting);
}
int32_t ModuleSettings::GetInt(const char* setting) const
{
return SettingsStore::GetInstance().GetInt(setting);
}
void ModuleSettings::SetString(const char * setting, const char * value)
{
Settings::GetInstance().SetString(setting, value);
SettingsStore::GetInstance().SetString(setting, value);
}
void ModuleSettings::SetBool(const char * setting, bool value)
{
Settings::GetInstance().SetBool(setting, value);
SettingsStore::GetInstance().SetBool(setting, value);
}
void ModuleSettings::SetInt(const char * setting, int32_t value)
{
SettingsStore::GetInstance().SetInt(setting, value);
}
void ModuleSettings::SetDefaultBool(const char * setting, bool value)
{
SettingsStore::GetInstance().SetDefaultBool(setting, value);
}
void ModuleSettings::SetDefaultInt(const char * setting, int32_t value)
{
SettingsStore::GetInstance().SetDefaultInt(setting, value);
}
void ModuleSettings::SetDefaultString(const char * setting, const char * value)
{
SettingsStore::GetInstance().SetDefaultString(setting, value);
}
const char * ModuleSettings::GetSectionSettings(const char * section) const
{
JsonValue json = SettingsStore::GetInstance().GetSettings(section);
m_sectionSetting = json.isNull() ? "" : JsonStyledWriter().write(json);
return m_sectionSetting.c_str();
}
void ModuleSettings::SetSectionSettings(const char * section, const std::string & json)
{
JsonValue root;
if (!json.empty())
{
JsonReader reader;
if (!reader.Parse(json.data(), json.data() + json.size(), root))
{
return;
}
}
SettingsStore& settings = SettingsStore::GetInstance();
settings.SetSettings(section, root);
settings.Save();
}
void ModuleSettings::RegisterCallback(const char* setting, SettingChangeCallback callback, void * userData)
{
SettingsStore::GetInstance().RegisterCallback(setting, callback, userData);
}
void ModuleSettings::UnregisterCallback(const char* setting, SettingChangeCallback callback, void* userData)
{
__debugbreak();
}

View File

@ -7,8 +7,23 @@ class ModuleSettings :
{
public:
//IModuleSettings
std::string GetString(const char * setting) const;
bool GetBool(const char * setting) const;
void SetString(const char * setting, const char * value);
void SetBool(const char * setting, bool value);
const char * GetString(const char * setting) const override;
bool GetBool(const char * setting) const override;
int32_t GetInt(const char * setting) const override;
void SetString(const char * setting, const char* value) override;
void SetBool(const char * setting, bool value) override;
void SetInt(const char * setting, int32_t value) override;
void SetDefaultBool(const char * setting, bool value) override;
void SetDefaultInt(const char * setting, int32_t value) override;
void SetDefaultString(const char * setting, const char * value) override;
const char * GetSectionSettings(const char * section) const override;
void SetSectionSettings(const char * section, const std::string & json) override;
void RegisterCallback(const char * setting, SettingChangeCallback callback, void * userData) override;
void UnregisterCallback(const char * setting, SettingChangeCallback callback, void * userData) override;
private:
mutable std::string m_sectionSetting;
};

View File

@ -105,6 +105,14 @@ void Modules::StopEmulation(void)
}
}
void Modules::FlushSettings(void)
{
for (BaseModules::iterator itr = m_baseModules.begin(); itr != m_baseModules.end(); itr++)
{
(*itr)->FlushSettings();
}
}
void Modules::CreateModules(void)
{
m_loaderFile = coreSettings.moduleLoaderSelected;

View File

@ -20,6 +20,7 @@ public:
bool Initialize(IRenderWindow & RenderWindow, ISwitchSystem & System);
void StartEmulation(void);
void StopEmulation(void);
void FlushSettings(void);
ISystemloader * Systemloader();
IVideo * Video(void);

View File

@ -23,6 +23,9 @@
</ImportGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<ClCompile>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
</ClCompile>
<PreBuildEvent>
<Command>"$(SolutionDir)src\script\update_version.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)src\nxemu-core\version.h.in" "$(SolutionDir)src\nxemu-core\version.h"</Command>
</PreBuildEvent>

View File

@ -28,10 +28,10 @@ struct CoreSettingsDefaults
static Path GetDefaultModuleDir();
};
void ModuleLoaderSelectedChanged(void);
void ModuleCpuSelectedChanged(void);
void ModuleVideoSelectedChanged(void);
void ModuleOsSelectedChanged(void);
void ModuleLoaderSelectedChanged(const char* /*setting*/, void* /*userData*/);
void ModuleCpuSelectedChanged(const char* /*setting*/, void* /*userData*/);
void ModuleVideoSelectedChanged(const char* /*setting*/, void* /*userData*/);
void ModuleOsSelectedChanged(const char* /*setting*/, void* /*userData*/);
} // namespace
CoreSettings coreSettings = {};
@ -45,14 +45,14 @@ Path CoreSettingsDefaults::GetDefaultModuleDir()
void LoadCoreSetting(void)
{
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
coreSettings = {};
coreSettings.configDir = Path(Path(settings.GetConfigFile()).GetDriveDirectory(), "");
coreSettings.moduleDir = CoreSettingsDefaults::GetDefaultModuleDir();
coreSettings.moduleDirValue = CoreSettingsDefaults::defaultModuleDirValue;
JsonValue jsonSettings = Settings::GetInstance().GetSettings("Core");
JsonValue jsonSettings = SettingsStore::GetInstance().GetSettings("Core");
const JsonValue * moduleDir = jsonSettings.Find("ModuleDirectory-x64");
if (moduleDir != nullptr && moduleDir->isString())
{
@ -118,10 +118,10 @@ void LoadCoreSetting(void)
settings.SetChanged(NXCoreSetting::ModuleOsSelected, strcmp(coreSettings.moduleOsSelected.c_str(), CoreSettingsDefaults::defaultModuleOperatingSystem) != 0);
settings.SetChanged(NXCoreSetting::ShowConsole, coreSettings.showConsole != CoreSettingsDefaults::defaultShowConsole);
Settings::GetInstance().RegisterCallback(NXCoreSetting::ModuleLoaderSelected, std::bind(&ModuleLoaderSelectedChanged));
Settings::GetInstance().RegisterCallback(NXCoreSetting::ModuleCpuSelected, std::bind(&ModuleCpuSelectedChanged));
Settings::GetInstance().RegisterCallback(NXCoreSetting::ModuleVideoSelected, std::bind(&ModuleVideoSelectedChanged));
Settings::GetInstance().RegisterCallback(NXCoreSetting::ModuleOsSelected, std::bind(&ModuleOsSelectedChanged));
SettingsStore::GetInstance().RegisterCallback(NXCoreSetting::ModuleLoaderSelected, ModuleLoaderSelectedChanged, nullptr);
SettingsStore::GetInstance().RegisterCallback(NXCoreSetting::ModuleCpuSelected, ModuleCpuSelectedChanged, nullptr);
SettingsStore::GetInstance().RegisterCallback(NXCoreSetting::ModuleVideoSelected, ModuleVideoSelectedChanged, nullptr);
SettingsStore::GetInstance().RegisterCallback(NXCoreSetting::ModuleOsSelected, ModuleOsSelectedChanged, nullptr);
coreSettings.moduleLoaderSelected = settings.GetString(NXCoreSetting::ModuleLoaderSelected);
coreSettings.moduleCpuSelected = settings.GetString(NXCoreSetting::ModuleCpuSelected);
@ -164,40 +164,40 @@ void SaveCoreSetting(void)
json["ModuleDirectory-x64"] = JsonValue(coreSettings.moduleDirValue);
}
Settings & settings = Settings::GetInstance();
SettingsStore& settings = SettingsStore::GetInstance();
settings.SetSettings("Core", json);
settings.Save();
}
namespace
{
void ModuleLoaderSelectedChanged(void)
void ModuleLoaderSelectedChanged(const char * /*setting*/, void * /*userData*/)
{
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
coreSettings.moduleLoaderSelected = settings.GetString(NXCoreSetting::ModuleLoaderSelected);
settings.SetChanged(NXCoreSetting::ModuleLoaderSelected, strcmp(coreSettings.moduleLoaderSelected.c_str(), CoreSettingsDefaults::defaultModuleLoader) != 0);
SaveCoreSetting();
}
void ModuleCpuSelectedChanged(void)
void ModuleCpuSelectedChanged(const char* /*setting*/, void* /*userData*/)
{
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
coreSettings.moduleCpuSelected = settings.GetString(NXCoreSetting::ModuleCpuSelected);
settings.SetChanged(NXCoreSetting::ModuleCpuSelected, strcmp(coreSettings.moduleCpuSelected.c_str(), CoreSettingsDefaults::defaultModuleCpu) != 0);
SaveCoreSetting();
}
void ModuleVideoSelectedChanged(void)
void ModuleVideoSelectedChanged(const char* /*setting*/, void* /*userData*/)
{
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
coreSettings.moduleVideoSelected = settings.GetString(NXCoreSetting::ModuleVideoSelected);
settings.SetChanged(NXCoreSetting::ModuleVideoSelected, strcmp(coreSettings.moduleVideoSelected.c_str(), CoreSettingsDefaults::defaultModuleVideo) != 0);
SaveCoreSetting();
}
void ModuleOsSelectedChanged(void)
void ModuleOsSelectedChanged(const char* /*setting*/, void* /*userData*/)
{
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
coreSettings.moduleOsSelected = settings.GetString(NXCoreSetting::ModuleOsSelected);
settings.SetChanged(NXCoreSetting::ModuleOsSelected, strcmp(coreSettings.moduleOsSelected.c_str(), CoreSettingsDefaults::defaultModuleOperatingSystem) != 0);
SaveCoreSetting();

View File

@ -3,16 +3,16 @@
#include <common/json.h>
#include <common/path.h>
std::unique_ptr<Settings> Settings::s_instance;
std::unique_ptr<SettingsStore> SettingsStore::s_instance;
Settings::Settings()
SettingsStore::SettingsStore()
{
Path congFilePath(Path::MODULE_DIRECTORY, "NxEmu.config");
congFilePath.AppendDirectory("config");
m_configPath = (const char *)congFilePath;
}
bool Settings::Initialize()
bool SettingsStore::Initialize()
{
m_details = JsonValue();
for (size_t i = 0; i < 100; i++)
@ -56,12 +56,12 @@ bool Settings::Initialize()
return true;
}
const char * Settings::GetConfigFile(void) const
const char * SettingsStore::GetConfigFile(void) const
{
return m_configPath.c_str();
}
void Settings::SetChanged(const char * setting, bool changed)
void SettingsStore::SetChanged(const char * setting, bool changed)
{
if (setting == nullptr)
{
@ -70,7 +70,7 @@ void Settings::SetChanged(const char * setting, bool changed)
m_settingsChanged[setting] = changed;
}
JsonValue Settings::GetSettings(const char * section) const
JsonValue SettingsStore::GetSettings(const char * section) const
{
const JsonValue * value = m_details.Find(section);
if (value != nullptr)
@ -80,22 +80,29 @@ JsonValue Settings::GetSettings(const char * section) const
return JsonValue();
}
void Settings::SetSettings(const char * section, JsonValue & json)
void SettingsStore::SetSettings(const char * section, JsonValue & json)
{
m_details[section] = json;
if (json.isNull())
{
m_details.removeMember(section);
}
else
{
m_details[section] = json;
}
}
std::string Settings::GetDefaultString(const char * setting) const
const char * SettingsStore::GetDefaultString(const char * setting) const
{
SettingsMapString::const_iterator itr = m_settingsDefaultString.find(setting);
if (itr == m_settingsDefaultString.end())
{
return "";
}
return itr->second;
return itr->second.c_str();
}
bool Settings::GetDefaultBool(const char * setting) const
bool SettingsStore::GetDefaultBool(const char * setting) const
{
SettingsMapBool::const_iterator itr = m_settingsDefaultBool.find(setting);
if (itr == m_settingsDefaultBool.end())
@ -105,17 +112,27 @@ bool Settings::GetDefaultBool(const char * setting) const
return itr->second;
}
std::string Settings::GetString(const char * setting) const
int32_t SettingsStore::GetDefaultInt(const char* setting) const
{
SettingsMapInt::const_iterator itr = m_settingsDefaultInt.find(setting);
if (itr == m_settingsDefaultInt.end())
{
return false;
}
return itr->second;
}
const char * SettingsStore::GetString(const char * setting) const
{
SettingsMapString::const_iterator itr = m_settingsString.find(setting);
if (itr == m_settingsString.end())
{
return GetDefaultString(setting);
}
return itr->second;
return itr->second.c_str();
}
bool Settings::GetBool(const char * setting) const
bool SettingsStore::GetBool(const char * setting) const
{
SettingsMapBool::const_iterator itr = m_settingsBool.find(setting);
if (itr == m_settingsBool.end())
@ -125,7 +142,7 @@ bool Settings::GetBool(const char * setting) const
return itr->second;
}
bool Settings::GetChanged(const char * setting) const
bool SettingsStore::GetChanged(const char * setting) const
{
SettingsMapBool::const_iterator itr = m_settingsChanged.find(setting);
if (itr == m_settingsChanged.end())
@ -135,7 +152,17 @@ bool Settings::GetChanged(const char * setting) const
return itr->second;
}
void Settings::SetDefaultString(const char * setting, const char * value)
int32_t SettingsStore::GetInt(const char* setting) const
{
SettingsMapInt::const_iterator itr = m_settingsInt.find(setting);
if (itr == m_settingsInt.end())
{
return GetDefaultInt(setting);
}
return itr->second;
}
void SettingsStore::SetDefaultString(const char * setting, const char * value)
{
if (setting == nullptr || value == nullptr)
{
@ -144,12 +171,17 @@ void Settings::SetDefaultString(const char * setting, const char * value)
m_settingsDefaultString[setting] = value;
}
void Settings::SetDefaultBool(const char * setting, bool value)
void SettingsStore::SetDefaultBool(const char * setting, bool value)
{
m_settingsDefaultBool[setting] = value;
}
void Settings::SetString(const char * setting, const char * value)
void SettingsStore::SetDefaultInt(const char * setting, int32_t value)
{
m_settingsDefaultInt[setting] = value;
}
void SettingsStore::SetString(const char * setting, const char * value)
{
if (setting == nullptr || value == nullptr)
{
@ -165,7 +197,7 @@ void Settings::SetString(const char * setting, const char * value)
NotifyChange(setting);
}
void Settings::SetBool(const char * setting, bool value)
void SettingsStore::SetBool(const char * setting, bool value)
{
if (setting == nullptr)
{
@ -181,7 +213,23 @@ void Settings::SetBool(const char * setting, bool value)
NotifyChange(setting);
}
void Settings::Save(void)
void SettingsStore::SetInt(const char * setting, int32_t value)
{
if (setting == nullptr)
{
return;
}
SettingsMapInt::const_iterator it = m_settingsInt.find(setting);
if (it != m_settingsInt.end() && it->second == value)
{
return;
}
m_settingsInt[setting] = value;
NotifyChange(setting);
}
void SettingsStore::Save(void)
{
std::string jsonStr = JsonStyledWriter().write(m_details);
Path(m_configPath).DirectoryCreate();
@ -193,26 +241,32 @@ void Settings::Save(void)
configFile.Write(jsonStr.c_str(), (uint32_t)jsonStr.length());
}
void Settings::RegisterCallback(const std::string & setting, std::function<void()> callback)
void SettingsStore::RegisterCallback(const std::string & setting, SettingChangeCallback callback, void * userData)
{
m_notification[setting].emplace_back(callback);
if (callback == nullptr)
{
return;
}
CallbackInfo info = { callback, userData };
m_notification[setting].emplace_back(info);
}
Settings & Settings::GetInstance()
SettingsStore & SettingsStore::GetInstance()
{
if (s_instance == nullptr)
{
s_instance = std::make_unique<Settings>();
s_instance = std::make_unique<SettingsStore>();
}
return *s_instance;
}
void Settings::CleanUp()
void SettingsStore::CleanUp()
{
s_instance.reset();
}
void Settings::NotifyChange(const char * setting)
void SettingsStore::NotifyChange(const char * setting)
{
if (setting == nullptr)
{
@ -224,10 +278,7 @@ void Settings::NotifyChange(const char * setting)
const NotificationCallbacks & callbacks = itr->second;
for (NotificationCallbacks::const_iterator callItr = callbacks.begin(); callItr != callbacks.end(); callItr++)
{
if (*callItr)
{
(*callItr)();
}
callItr->callback(setting, callItr->userData);
}
}
}

View File

@ -1,19 +1,27 @@
#pragma once
#include <nxemu-module-spec/base.h>
#include <common/json.h>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
class Settings
class SettingsStore
{
struct CallbackInfo
{
SettingChangeCallback callback;
void * userData;
};
typedef std::unordered_map<std::string, std::string> SettingsMapString;
typedef std::unordered_map<std::string, bool> SettingsMapBool;
typedef std::vector<std::function<void()>> NotificationCallbacks;
typedef std::unordered_map<std::string, int32_t> SettingsMapInt;
typedef std::vector<CallbackInfo> NotificationCallbacks;
typedef std::unordered_map<std::string, NotificationCallbacks> NotificationMap;
public:
Settings();
SettingsStore();
bool Initialize();
const char * GetConfigFile(void) const;
@ -21,22 +29,26 @@ public:
JsonValue GetSettings(const char * section) const;
void SetSettings(const char * section, JsonValue & json);
std::string GetDefaultString(const char * setting) const;
const char * GetDefaultString(const char * setting) const;
bool GetDefaultBool(const char * setting) const;
std::string GetString(const char * setting) const;
bool GetBool(const char * setting) const;
int GetDefaultInt(const char * setting) const;
const char * GetString(const char * setting) const;
bool GetBool(const char* setting) const;
bool GetChanged(const char * setting) const;
int32_t GetInt(const char* setting) const;
void SetDefaultString(const char * setting, const char * value);
void SetDefaultBool(const char * setting, bool value);
void SetDefaultInt(const char * setting, const int32_t value);
void SetString(const char * setting, const char * value);
void SetBool(const char * setting, bool value);
void SetInt(const char * setting, int32_t value);
void SetChanged(const char * setting, bool changed);
void Save(void);
void RegisterCallback(const std::string & setting, std::function<void()> callback);
void RegisterCallback(const std::string & setting, SettingChangeCallback callback, void * userData);
static Settings & GetInstance();
static SettingsStore& GetInstance();
static void CleanUp();
private:
@ -44,12 +56,14 @@ private:
SettingsMapString m_settingsString;
SettingsMapBool m_settingsBool;
SettingsMapInt m_settingsInt;
SettingsMapString m_settingsDefaultString;
SettingsMapBool m_settingsDefaultBool;
SettingsMapInt m_settingsDefaultInt;
SettingsMapBool m_settingsChanged;
NotificationMap m_notification;
static std::unique_ptr<Settings> s_instance;
static std::unique_ptr<SettingsStore> s_instance;
std::string m_configPath;
JsonValue m_details;
};

View File

@ -71,6 +71,16 @@ void CALL EmulationStopping()
{
}
/*
Function: FlushSettings
Purpose: Called when emulation is saving settings
Input: None
Output: None
*/
EXPORT void CALL FlushSettings()
{
}
ICpu * CALL CreateCpu(ISwitchSystem & System)
{
if (g_cpuManager.get() != nullptr)

View File

@ -71,6 +71,16 @@ void CALL EmulationStopping()
{
}
/*
Function: FlushSettings
Purpose: Called when emulation is saving settings
Input: None
Output: None
*/
EXPORT void CALL FlushSettings()
{
}
ISystemloader * CALL CreateSystemLoader(ISwitchSystem & System)
{
if (g_loaderManager.get() != nullptr)

View File

@ -16,10 +16,10 @@
enum
{
MODULE_LOADER_SPECS_VERSION = 0x0106,
MODULE_VIDEO_SPECS_VERSION = 0x0107,
MODULE_CPU_SPECS_VERSION = 0x0102,
MODULE_OPERATING_SYSTEM_SPECS_VERSION = 0x0106,
MODULE_LOADER_SPECS_VERSION = 0x0107,
MODULE_VIDEO_SPECS_VERSION = 0x0108,
MODULE_CPU_SPECS_VERSION = 0x0103,
MODULE_OPERATING_SYSTEM_SPECS_VERSION = 0x0107,
};
enum MODULE_TYPE : uint16_t
@ -36,12 +36,26 @@ __interface IModuleNotification
void BreakPoint(const char * fileName, uint32_t lineNumber) = 0;
};
typedef void (*SettingChangeCallback)(const char * setting, void * userData);
__interface IModuleSettings
{
std::string GetString(const char * setting) const = 0;
const char * GetString(const char * setting) const = 0;
bool GetBool(const char * setting) const = 0;
int32_t GetInt(const char * setting) const = 0;
void SetString(const char * setting, const char * value) = 0;
void SetBool(const char * setting, bool value) = 0;
void SetInt(const char * setting, int32_t value) = 0;
void SetDefaultBool(const char * setting, bool value) = 0;
void SetDefaultInt(const char * setting, int value) = 0;
void SetDefaultString(const char * setting, const char * value) = 0;
const char * GetSectionSettings(const char * section) const = 0;
void SetSectionSettings(const char * section, const std::string & json) = 0;
void RegisterCallback(const char * setting, SettingChangeCallback callback, void * userData) = 0;
void UnregisterCallback(const char * setting, SettingChangeCallback callback, void * userData) = 0;
};
typedef struct
@ -117,3 +131,11 @@ Input: None
Output: None
*/
EXPORT void CALL EmulationStopping();
/*
Function: FlushSettings
Purpose: Called when emulation is saving settings
Input: None
Output: None
*/
EXPORT void CALL FlushSettings();

View File

@ -79,6 +79,7 @@ __interface IOperatingSystem
void KeyboardKeyRelease(int modifier, int keyIndex, int keyCode) = 0;
void GatherGPUDirtyMemory(ICacheInvalidator * invalidator) = 0;
void GameFrameEnd() = 0;
void AudioGetSyncIDs(uint32_t * ids, uint32_t maxCount, uint32_t * actualCount) = 0;
};
EXPORT IOperatingSystem * CALL CreateOperatingSystem(ISwitchSystem & system);

View File

@ -1,4 +1,5 @@
#include "os_manager.h"
#include "os_settings.h"
#include <memory>
#include <stdio.h>
@ -72,6 +73,17 @@ void CALL EmulationStopping()
{
}
/*
Function: FlushSettings
Purpose: Called when emulation is saving settings
Input: None
Output: None
*/
EXPORT void CALL FlushSettings()
{
SaveOsSettings();
}
IOperatingSystem * CALL CreateOperatingSystem(ISwitchSystem & System)
{
if (g_osManager.get() != nullptr)

View File

@ -40,7 +40,7 @@
<Link>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)\external\boost\stage\lib\libboost_context-vc143-mt-s-x64-1_87.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\external\boost\stage\lib\libboost_context-vc143-mt-sgd-x64-1_87.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>ntdll.lib;Iphlpapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>ntdll.lib;Iphlpapi.lib;winmm.lib;ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@ -456,6 +456,7 @@
<ClCompile Include="core\hle\service\vi\vi.cpp" />
<ClCompile Include="core\hle\service\vi\vsync_manager.cpp" />
<ClCompile Include="os_manager.cpp" />
<ClCompile Include="os_settings.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="version.h.in" />
@ -925,6 +926,8 @@
<ClInclude Include="core\perf_stats.h" />
<ClInclude Include="nxemu-os.h" />
<ClInclude Include="os_manager.h" />
<ClInclude Include="os_settings.h" />
<ClInclude Include="os_settings_identifiers.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\external\cubeb.vcxproj">
@ -948,6 +951,9 @@
<ProjectReference Include="..\3rd_party\tz\tz.vcxproj">
<Project>{677ca72d-e9b7-4aa5-adba-1c02ac84f8b0}</Project>
</ProjectReference>
<ProjectReference Include="..\common\common.vcxproj">
<Project>{ec81be93-8316-4db6-8a26-b13fb5b13848}</Project>
</ProjectReference>
<ProjectReference Include="..\network\network.vcxproj">
<Project>{286ff3b0-952d-4193-94ab-c8c300bc85f0}</Project>
</ProjectReference>

View File

@ -1893,6 +1893,12 @@
<ClInclude Include="core\hle\service\audio\hardware_opus_decoder.h">
<Filter>Header Files\core\hle\service\audio</Filter>
</ClInclude>
<ClInclude Include="os_settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="os_settings_identifiers.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="version.h.in">
@ -3181,5 +3187,8 @@
<ClCompile Include="core\hle\service\audio\hardware_opus_decoder.cpp">
<Filter>Source Files\core\hle\service\audio</Filter>
</ClCompile>
<ClCompile Include="os_settings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -10,7 +10,9 @@
#include "yuzu_hid_core/hid_core.h"
#include "yuzu_input_common/main.h"
#include "yuzu_input_common/drivers/keyboard.h"
#include "yuzu_audio_core/sink/sink_details.h"
#include "os_manager.h"
#include "os_settings.h"
extern IModuleSettings * g_settings;
@ -38,6 +40,8 @@ void OSManager::EmulationStarting()
bool OSManager::Initialize(void)
{
SetupOsSetting();
Common::Log::Initialize();
Common::Log::Start();
Common::Log::SetColorConsoleBackendEnabled(g_settings->GetBool(NXCoreSetting::ShowConsole));
@ -156,3 +160,17 @@ void OSManager::GameFrameEnd()
{
m_coreSystem.GetPerfStats().EndGameFrame();
}
void OSManager::AudioGetSyncIDs(uint32_t * ids, uint32_t maxCount, uint32_t* actualCount)
{
std::vector<Settings::AudioEngine> sinkIds = AudioCore::Sink::GetSinkIDs();
if (actualCount)
{
*actualCount = (uint32_t)sinkIds.size();
}
if (ids != nullptr && maxCount > 0 && sinkIds.size() > 0)
{
memcpy(ids, sinkIds.data(), std::min(maxCount, (uint32_t)sinkIds.size()) * sizeof(uint32_t));
}
}

View File

@ -21,6 +21,7 @@ public:
void KeyboardKeyRelease(int modifier, int keyIndex, int keyCode) override;
void GatherGPUDirtyMemory(ICacheInvalidator * invalidator) override;
void GameFrameEnd() override;
void AudioGetSyncIDs(uint32_t* ids, uint32_t maxCount, uint32_t* actualCount) override;
private:
OSManager() = delete;

View File

@ -0,0 +1,58 @@
#include "os_settings.h"
#include "os_settings_identifiers.h"
#include <common/json.h>
#include <nxemu-module-spec/base.h>
#include <yuzu_common/settings_enums.h>
#include <yuzu_common/settings.h>
extern IModuleSettings * g_settings;
void OsSettingChanged(const char * setting, void * userData)
{
if (strcmp(NXOsSetting::AudioSinkId, setting) == 0)
{
Settings::values.sink_id.SetValue((Settings::AudioEngine)g_settings->GetInt(NXOsSetting::AudioSinkId));
}
}
void SetupOsSetting(void)
{
std::string json = g_settings->GetSectionSettings("nxemu-os");
Settings::values.sink_id.SetValue(Settings::values.sink_id.GetDefault());
JsonValue root;
JsonReader reader;
if (!json.empty() && reader.Parse(json.data(), json.data() + json.size(), root))
{
JsonValue audio = root["audio"];
if (audio.isObject())
{
JsonValue value = audio["sink_id"];
if (value.isString())
{
Settings::values.sink_id.SetValue(Settings::ToEnum<Settings::AudioEngine>(value.asString()));
}
}
}
g_settings->SetDefaultInt(NXOsSetting::AudioSinkId, (int32_t)Settings::values.sink_id.GetDefault());
g_settings->SetInt(NXOsSetting::AudioSinkId, (int32_t)Settings::values.sink_id.GetValue());
g_settings->RegisterCallback(NXOsSetting::AudioSinkId, OsSettingChanged, nullptr);
}
void SaveOsSettings(void)
{
JsonValue json_audio;
if (Settings::values.sink_id.GetValue() != Settings::values.sink_id.GetDefault())
{
json_audio["sink_id"] = Settings::CanonicalizeEnum(Settings::values.sink_id.GetValue());
}
JsonValue json;
if (json_audio.size() > 0)
{
json["audio"] = json_audio;
}
g_settings->SetSectionSettings("nxemu-os", json.isNull() ? "" : JsonStyledWriter().write(json));
}

View File

@ -0,0 +1,4 @@
#pragma once
void SetupOsSetting(void);
void SaveOsSettings(void);

View File

@ -0,0 +1,7 @@
#pragma once
namespace NXOsSetting
{
constexpr const char * AudioSinkId = "nxos:AudioSinkId";
} // namespace NXCoreSetting

View File

@ -75,6 +75,16 @@ void CALL EmulationStopping()
{
}
/*
Function: FlushSettings
Purpose: Called when emulation is saving settings
Input: None
Output: None
*/
EXPORT void CALL FlushSettings()
{
}
IVideo * CALL CreateVideo(IRenderWindow & renderWindow, ISwitchSystem & system)
{
if (g_notify == nullptr)

View File

@ -6,12 +6,14 @@
#include <nxemu-core/app_init.h>
#include <nxemu-core/version.h>
#include <sciter_ui.h>
#include <widgets/combo_box.h>
#include <widgets/menubar.h>
#include <widgets/page_nav.h>
#include <windows.h>
void RegisterWidgets(ISciterUI & sciterUI)
{
Register_WidgetComboBox(sciterUI);
Register_WidgetMenuBar(sciterUI);
Register_WidgetPageNav(sciterUI);
}

View File

@ -25,6 +25,7 @@
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)external\sciterui\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
</ClCompile>
<PreBuildEvent>
<Command>IF NOT EXIST "$(SolutionDir)config\NxEmu.config" (copy "$(SolutionDir)config\NxEmu.config.development" "$(SolutionDir)config\NxEmu.config")

View File

@ -27,7 +27,7 @@ void LoadUISetting(void)
uiSettings.languageCurrent = UISettingsDefaults::defaultLanguageCurrentValue;
uiSettings.sciterConsole = UISettingsDefaults::defaultSciterConsole;
JsonValue jsonSettings = Settings::GetInstance().GetSettings("UI");
JsonValue jsonSettings = SettingsStore::GetInstance().GetSettings("UI");
const JsonValue * node = jsonSettings.Find("LanguageDirectory");
if (node != nullptr && node->isString())
@ -77,7 +77,7 @@ void SaveUISetting(void)
{
json["LanguageDirectory"] = JsonValue(uiSettings.languageDirValue);
}
Settings & settings = Settings::GetInstance();
SettingsStore & settings = SettingsStore::GetInstance();
settings.SetSettings("UI", json);
settings.Save();
}

View File

@ -19,11 +19,11 @@ SciterMainWindow::SciterMainWindow(ISciterUI & sciterUI, const char * windowTitl
m_windowTitle(windowTitle),
m_systemConfig(sciterUI)
{
Settings & settings = Settings::GetInstance();
settings.RegisterCallback(NXCoreSetting::GameFile, std::bind(&SciterMainWindow::GameFileChanged, this));
settings.RegisterCallback(NXCoreSetting::GameName, std::bind(&SciterMainWindow::GameNameChanged, this));
settings.RegisterCallback(NXCoreSetting::RomLoading, std::bind(&SciterMainWindow::RomLoadingChanged, this));
settings.RegisterCallback(NXCoreSetting::DisplayedFrames, std::bind(&SciterMainWindow::DisplayedFramesChanged, this));
SettingsStore & settings = SettingsStore::GetInstance();
settings.RegisterCallback(NXCoreSetting::GameFile, SciterMainWindow::GameFileChanged, this);
settings.RegisterCallback(NXCoreSetting::GameName, SciterMainWindow::GameNameChanged, this);
settings.RegisterCallback(NXCoreSetting::RomLoading, SciterMainWindow::RomLoadingChanged, this);
settings.RegisterCallback(NXCoreSetting::DisplayedFrames, SciterMainWindow::DisplayedFramesChanged, this);
}
void SciterMainWindow::ResetMenu()
@ -83,10 +83,10 @@ bool SciterMainWindow::Show(void)
SetCaption(m_windowTitle);
SciterElement menuElement(rootElement.GetElementByID("MainMenu"));
void * interfacePtr = nullptr;
if (menuElement.IsValid() && m_sciterUI.GetElementInterface(menuElement, IID_IMENUBAR, &interfacePtr))
std::shared_ptr<void> interfacePtr = menuElement.IsValid() ? m_sciterUI.GetElementInterface(menuElement, IID_IMENUBAR) : nullptr;
if (interfacePtr)
{
m_menuBar = std::shared_ptr<IMenuBar>(reinterpret_cast<IMenuBar *>(interfacePtr), [](IMenuBar *) {});
m_menuBar = std::static_pointer_cast<IMenuBar>(interfacePtr);
ResetMenu();
}
m_sciterUI.UpdateWindow(rootElement.GetElementHwnd(true));
@ -295,15 +295,17 @@ void SciterMainWindow::SetCaption(const std::string & caption)
}
}
void SciterMainWindow::GameFileChanged(void)
void SciterMainWindow::GameFileChanged(const char * /*setting*/, void * userData)
{
SciterMainWindow * impl = (SciterMainWindow *)userData;
enum
{
maxRememberedFiles = 10
};
Stringlist & recentFiles = uiSettings.recentFiles;
std::string gameFile = Settings::GetInstance().GetString(NXCoreSetting::GameFile);
std::string gameFile = SettingsStore::GetInstance().GetString(NXCoreSetting::GameFile);
for (Stringlist::const_iterator itr = recentFiles.begin(); itr != recentFiles.end(); itr++)
{
if (_stricmp(gameFile.c_str(), itr->c_str()) != 0)
@ -318,41 +320,47 @@ void SciterMainWindow::GameFileChanged(void)
{
recentFiles.resize(maxRememberedFiles);
}
ResetMenu();
impl->ResetMenu();
SaveUISetting();
}
void SciterMainWindow::GameNameChanged(void)
void SciterMainWindow::GameNameChanged(const char * /*setting*/, void * userData)
{
std::string gameName = Settings::GetInstance().GetString(NXCoreSetting::GameName);
SciterMainWindow * impl = (SciterMainWindow *)userData;
std::string gameName = SettingsStore::GetInstance().GetString(NXCoreSetting::GameName);
if (gameName.length() > 0)
{
std::string caption;
caption += gameName;
caption += " | ";
caption += m_windowTitle;
SetCaption(caption);
caption += impl->m_windowTitle;
impl->SetCaption(caption);
}
}
void SciterMainWindow::RomLoadingChanged(void)
void SciterMainWindow::RomLoadingChanged(const char * /*setting*/, void * userData)
{
bool loading = Settings::GetInstance().GetBool(NXCoreSetting::RomLoading);
SciterMainWindow * impl = (SciterMainWindow*)userData;
bool loading = SettingsStore::GetInstance().GetBool(NXCoreSetting::RomLoading);
if (loading)
{
ShowLoadingScreen();
impl->ShowLoadingScreen();
}
}
void SciterMainWindow::DisplayedFramesChanged(void)
void SciterMainWindow::DisplayedFramesChanged(const char * /*setting*/, void * userData)
{
SciterElement rootElement(m_window->GetRootElement());
SciterMainWindow * impl = (SciterMainWindow*)userData;
SciterElement rootElement(impl->m_window->GetRootElement());
SciterElement mainContents(rootElement.GetElementByID("MainContents"));
if (mainContents.IsValid())
{
mainContents.SetHTML((uint8_t *)"", 0, SciterElement::SIH_REPLACE_CONTENT);
}
ShowWindow((HWND)m_renderWindow, SW_SHOW);
ShowWindow((HWND)impl->m_renderWindow, SW_SHOW);
}
void SciterMainWindow::OnOpenFile(void)

View File

@ -2,6 +2,7 @@
#include <memory>
#include <nxemu-core/modules/module_base.h>
#include <sciter_ui.h>
#include <sciter_handler.h>
#include <widgets/menubar.h>
#include "user_interface/settings/system_config.h"
@ -39,10 +40,10 @@ private:
SciterMainWindow & operator=(const SciterMainWindow &) = delete;
void SetCaption(const std::string & caption);
void GameFileChanged(void);
void GameNameChanged(void);
void RomLoadingChanged(void);
void DisplayedFramesChanged(void);
static void GameFileChanged(const char * setting, void * userData);
static void GameNameChanged(const char * setting, void * userData);
static void RomLoadingChanged(const char * setting, void * userData);
static void DisplayedFramesChanged(const char * setting, void * userData);
void ShowLoadingScreen(void);
int32_t SciterKeyToSwitchKey(SciterKeys key);
int32_t SciterKeyToVKCode(SciterKeys vkcode);

View File

@ -1,7 +1,9 @@
#include "system_config.h"
#include "system_config_audio.h"
#include <nxemu-core/machine/switch_system.h>
#include <sciter_ui.h>
#include <sciter_element.h>
#include <sciter_handler.h>
#include <widgets/page_nav.h>
SystemConfig::SystemConfig(ISciterUI & SciterUI) :
@ -30,37 +32,58 @@ void SystemConfig::Display(void * parentWindow)
if (root.IsValid())
{
SciterElement pageNav = root.GetElementByID("MainTabNav");
if (pageNav.IsValid())
std::shared_ptr<void> interfacePtr = pageNav.IsValid() ? m_sciterUI.GetElementInterface(pageNav, IID_IPAGENAV) : nullptr;
if (interfacePtr)
{
void * interfacePtr = nullptr;
if (m_sciterUI.GetElementInterface(pageNav, IID_IPAGENAV, &interfacePtr))
{
m_pageNav = std::shared_ptr<IPageNav>(reinterpret_cast<IPageNav*>(interfacePtr), [](IPageNav*) {});
m_pageNav->AddSink(this);
}
m_pageNav = std::static_pointer_cast<IPageNav>(interfacePtr);
m_pageNav->AddSink(this);
}
SciterElement okButton = root.FindFirst("button[role=\"window-ok\"]");
m_sciterUI.AttachHandler(okButton, IID_ICLICKSINK, (IClickSink*)this);
}
}
bool SystemConfig::PageNavChangeFrom(const std::string& PageName, SCITER_ELEMENT PageNav)
bool SystemConfig::PageNavChangeFrom(const std::string & /*pageName*/, SCITER_ELEMENT /*pageNav*/)
{
return true;
}
bool SystemConfig::PageNavChangeTo(const std::string& PageName, SCITER_ELEMENT PageNav)
bool SystemConfig::PageNavChangeTo(const std::string & /*pageName*/, SCITER_ELEMENT /*pageNav*/)
{
return true;
}
void SystemConfig::PageNavCreatedPage(const std::string& PageName, SCITER_ELEMENT Page)
void SystemConfig::PageNavCreatedPage(const std::string & pageName, SCITER_ELEMENT page)
{
if (PageName == "Audio")
if (pageName == "Audio")
{
m_systemConfigAudio.reset(new SystemConfigAudio(m_sciterUI, m_window->GetHandle(), Page));
m_systemConfigAudio.reset(new SystemConfigAudio(m_sciterUI, m_window->GetHandle(), page));
}
}
void SystemConfig::PageNavPageChanged(const std::string& PageName, SCITER_ELEMENT PageNav)
void SystemConfig::PageNavPageChanged(const std::string & /*pageName*/, SCITER_ELEMENT /*pageNav*/)
{
}
bool SystemConfig::OnClick(SCITER_ELEMENT element, SCITER_ELEMENT /*source*/, uint32_t /*reason*/)
{
SciterElement clickElem(element);
if (clickElem.GetAttribute("role") == "window-ok")
{
if (m_systemConfigAudio)
{
m_systemConfigAudio->SaveSetting();
}
SwitchSystem * system = SwitchSystem::GetInstance();
if (system != nullptr)
{
system->FlushSettings();
}
m_window->Destroy();
}
return false;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <sciter_handler.h>
#include <widgets/page_nav.h>
__interface ISciterUI;
@ -6,7 +7,8 @@ __interface ISciterWindow;
class SystemConfigAudio;
class SystemConfig :
public IPagesSink
public IPagesSink,
public IClickSink
{
public:
SystemConfig(ISciterUI& SciterUI);
@ -15,10 +17,13 @@ public:
void Display(void* parentWindow);
// IPagesSink
bool PageNavChangeFrom(const std::string& PageName, SCITER_ELEMENT PageNav) override;
bool PageNavChangeTo(const std::string& PageName, SCITER_ELEMENT PageNav) override;
void PageNavCreatedPage(const std::string& PageName, SCITER_ELEMENT Page) override;
void PageNavPageChanged(const std::string& PageName, SCITER_ELEMENT PageNav) override;
bool PageNavChangeFrom(const std::string & pageName, SCITER_ELEMENT pageNav) override;
bool PageNavChangeTo(const std::string & pageName, SCITER_ELEMENT pageNav) override;
void PageNavCreatedPage(const std::string & pageName, SCITER_ELEMENT page) override;
void PageNavPageChanged(const std::string & pageName, SCITER_ELEMENT pageNav) override;
//IClickSink
bool OnClick(SCITER_ELEMENT element, SCITER_ELEMENT source, uint32_t reason) override;
private:
SystemConfig() = delete;

View File

@ -1,8 +1,65 @@
#include "system_config_audio.h"
#include <common/std_string.h>
#include <nxemu-core/settings/settings.h>
#include <widgets/combo_box.h>
#include <yuzu_common/settings_enums.h>
#include <nxemu-core/machine/switch_system.h>
#include <nxemu-os/os_settings_identifiers.h>
SystemConfigAudio::SystemConfigAudio(ISciterUI & sciterUI, HWINDOW parent, SciterElement page) :
m_sciterUI(sciterUI),
m_parent(parent),
m_page(page)
{
SwitchSystem * system = SwitchSystem::GetInstance();
if (system == nullptr)
{
return;
}
IOperatingSystem & OperatingSystem = system->OperatingSystem();
uint32_t count = 0;
OperatingSystem.AudioGetSyncIDs(nullptr, 0, &count);
std::vector<uint32_t> ids(count);
OperatingSystem.AudioGetSyncIDs(ids.data(), count, &count);
SettingsStore & settings = SettingsStore::GetInstance();
int32_t AudioSinkId = settings.GetInt(NXOsSetting::AudioSinkId);
std::shared_ptr<void> interfacePtr = m_sciterUI.GetElementInterface(page.GetElementByID("audioOutputEngine"), IID_ICOMBOBOX);
if (interfacePtr)
{
m_outputEngine = std::static_pointer_cast<IComboBox>(interfacePtr);
int32_t index = m_outputEngine->AddItem("auto", stdstr_f("%d", Settings::AudioEngine::Auto).c_str());
int32_t selectedIndex = -1;
if (AudioSinkId == (int32_t)Settings::AudioEngine::Auto)
{
selectedIndex = index;
}
for (size_t i = 0, n = ids.size(); i < n; i++)
{
index = m_outputEngine->AddItem(Settings::CanonicalizeEnum((Settings::AudioEngine)ids[i]).c_str(), stdstr_f("%d", ids[i]).c_str());
if (AudioSinkId == (int32_t)ids[i])
{
selectedIndex = index;
}
}
if (selectedIndex >= 0)
{
m_outputEngine->SelectItem(selectedIndex);
}
}
}
void SystemConfigAudio::SaveSetting(void)
{
SettingsStore & settings = SettingsStore::GetInstance();
SciterElement outputEngine = m_outputEngine->GetSelectedItem();
if (outputEngine)
{
std::string value = outputEngine.GetAttribute("value");
if (value.size() > 0)
{
settings.SetInt(NXOsSetting::AudioSinkId, std::stoi(value));
}
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <sciter_ui.h>
#include <sciter_element.h>
#include <widgets/combo_box.h>
class SystemConfigAudio
{
@ -8,6 +9,8 @@ public:
SystemConfigAudio(ISciterUI & sciterUI, HWINDOW parent, SciterElement page);
~SystemConfigAudio() = default;
void SaveSetting(void);
private:
SystemConfigAudio() = delete;
SystemConfigAudio(const SystemConfigAudio &) = delete;
@ -16,4 +19,5 @@ private:
ISciterUI & m_sciterUI;
HWINDOW m_parent;
SciterElement m_page;
std::shared_ptr<IComboBox> m_outputEngine;
};

View File

@ -26,7 +26,7 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<UseStandardPreprocessor>true</UseStandardPreprocessor>
<PreprocessorDefinitions>NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>HAVE_CUBEB=1;HAVE_SDL2;NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)external\boost;$(SolutionDir)external\cubeb\include;$(SolutionDir)external\fmt\include;$(SolutionDir)external\opus\include;$(SolutionDir)external\sdl\include;$(SolutionDir)src\3rd_party\cubeb;$(SolutionDir)src\3rd_party\microprofile;$(SolutionDir)src\nxemu-os;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>