Feature: Allow choosing audio backend (#1588)

* Fix X11 being searched for on macOS

* Add ability to switch audio backends

* Fix issues with c arrays of std dynamic size items

* Fix old uses of sizeof()

* Remove current selected option from list

* Don’t show items if we only have one option
This commit is contained in:
David Chavez 2022-09-27 01:48:47 +02:00 committed by GitHub
parent 0e1248f840
commit dbc4d8199e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 40 deletions

View File

@ -19,6 +19,6 @@ namespace Ship {
#include "WasapiAudioPlayer.h" #include "WasapiAudioPlayer.h"
#elif defined(__linux) #elif defined(__linux)
#include "PulseAudioPlayer.h" #include "PulseAudioPlayer.h"
#else
#include "SDLAudioPlayer.h"
#endif #endif
#include "SDLAudioPlayer.h"

View File

@ -530,12 +530,11 @@ endif()
################################################################################ ################################################################################
# Compile and link options # Compile and link options
################################################################################ ################################################################################
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS") if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(SDL2) find_package(SDL2)
find_package(GLEW) find_package(GLEW)
find_package(X11) find_package(X11)
if (NOT GLEW_FOUND) if (NOT GLEW_FOUND)
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows|Darwin")
include (FetchContent) include (FetchContent)
FetchContent_Declare( FetchContent_Declare(
glew glew
@ -545,7 +544,6 @@ if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")
FetchContent_MakeAvailable(glew) FetchContent_MakeAvailable(glew)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/glew/build/cmake ${CMAKE_BINARY_DIR}/glew EXCLUDE_FROM_ALL) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/glew/build/cmake ${CMAKE_BINARY_DIR}/glew EXCLUDE_FROM_ALL)
endif() endif()
endif()
if (NOT GLEW_FOUND) if (NOT GLEW_FOUND)
set(GLEW-INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../../external/glew/include) set(GLEW-INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/../../external/glew/include)

View File

@ -84,7 +84,8 @@ namespace SohImGui {
std::function<void(void)> clientSetupHooks; std::function<void(void)> clientSetupHooks;
bool needs_save = false; bool needs_save = false;
int lastBackendID = 0; int lastRenderingBackendID = 0;
int lastAudioBackendID = 0;
bool statsWindowOpen; bool statsWindowOpen;
const char* filters[3] = { const char* filters[3] = {
@ -97,7 +98,7 @@ namespace SohImGui {
"None" "None"
}; };
std::pair<const char*, const char*> backends[] = { std::vector<std::pair<const char*, const char*>> renderingBackends = {
#ifdef _WIN32 #ifdef _WIN32
{ "dx11", "DirectX" }, { "dx11", "DirectX" },
#endif #endif
@ -108,6 +109,16 @@ namespace SohImGui {
#endif #endif
}; };
std::vector<std::pair<const char*, const char*>> audioBackends = {
#ifdef _WIN32
{ "wasapi", "Windows Audio Session API" },
#endif
#if defined(__linux)
{ "pulse", "PulseAudio" },
#endif
{ "sdl", "SDL Audio" }
};
std::map<std::string, std::vector<std::string>> hiddenwindowCategories; std::map<std::string, std::vector<std::string>> hiddenwindowCategories;
std::map<std::string, std::vector<std::string>> windowCategories; std::map<std::string, std::vector<std::string>> windowCategories;
std::map<std::string, CustomWindow> customWindows; std::map<std::string, CustomWindow> customWindows;
@ -130,19 +141,30 @@ namespace SohImGui {
}); });
} }
int GetBackendID(std::shared_ptr<Mercury> cfg) { void PopulateBackendIds(std::shared_ptr<Mercury> cfg) {
std::string backend = cfg->getString("Window.GfxBackend"); std::string renderingBackend = cfg->getString("Window.GfxBackend");
if (backend.empty()) { if (renderingBackend.empty()) {
return 0; lastRenderingBackendID = 0;
} else {
for (size_t i = 0; i < renderingBackends.size(); i++) {
if(renderingBackend == renderingBackends[i].first) {
lastRenderingBackendID = i;
break;
} }
for (size_t i = 0; i < (sizeof(backends) / sizeof(backends[0])); i++) {
if(backend == backends[i].first) {
return i;
} }
} }
return 0; std::string audioBackend = cfg->getString("Window.AudioBackend");
if (audioBackend.empty()) {
lastAudioBackendID = 0;
} else {
for (size_t i = 0; i < audioBackends.size(); i++) {
if(audioBackend == audioBackends[i].first) {
lastAudioBackendID = i;
break;
}
}
}
} }
void ImGuiWMInit() { void ImGuiWMInit() {
@ -344,7 +366,8 @@ namespace SohImGui {
io->DisplaySize.y = window_impl.gx2.height; io->DisplaySize.y = window_impl.gx2.height;
#endif #endif
lastBackendID = GetBackendID(Window::GetInstance()->GetConfig()); PopulateBackendIds(Window::GetInstance()->GetConfig());
if (CVar_GetS32("gOpenMenuBar", 0) != 1) { if (CVar_GetS32("gOpenMenuBar", 0) != 1) {
#if defined(__SWITCH__) || defined(__WIIU__) #if defined(__SWITCH__) || defined(__WIIU__)
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu"); SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
@ -726,17 +749,30 @@ namespace SohImGui {
return gfx_get_detected_hz(); return gfx_get_detected_hz();
} }
std::pair<const char*, const char*>* GetAvailableRenderingBackends() { std::vector<std::pair<const char*, const char*>> GetAvailableRenderingBackends() {
return backends; return renderingBackends;
}
std::vector<std::pair<const char*, const char*>> GetAvailableAudioBackends() {
return audioBackends;
} }
std::pair<const char*, const char*> GetCurrentRenderingBackend() { std::pair<const char*, const char*> GetCurrentRenderingBackend() {
return backends[lastBackendID]; return renderingBackends[lastRenderingBackendID];
}
std::pair<const char*, const char*> GetCurrentAudioBackend() {
return audioBackends[lastAudioBackendID];
} }
void SetCurrentRenderingBackend(uint8_t index, std::pair<const char*, const char*> backend) { void SetCurrentRenderingBackend(uint8_t index, std::pair<const char*, const char*> backend) {
Window::GetInstance()->GetConfig()->setString("Window.GfxBackend", backend.first); Window::GetInstance()->GetConfig()->setString("Window.GfxBackend", backend.first);
lastBackendID = index; lastRenderingBackendID = index;
}
void SetCurrentAudioBackend(uint8_t index, std::pair<const char*, const char*> backend) {
Window::GetInstance()->GetConfig()->setString("Window.AudioBackend", backend.first);
lastAudioBackendID = index;
} }
const char** GetSupportedTextureFilters() { const char** GetSupportedTextureFilters() {

View File

@ -80,13 +80,17 @@ namespace SohImGui {
Backend WindowBackend(); Backend WindowBackend();
float WindowRefreshRate(); float WindowRefreshRate();
std::pair<const char*, const char*>* GetAvailableRenderingBackends(); std::vector<std::pair<const char*, const char*>> GetAvailableRenderingBackends();
std::pair<const char*, const char*> GetCurrentRenderingBackend(); std::pair<const char*, const char*> GetCurrentRenderingBackend();
void SetCurrentRenderingBackend(uint8_t index, std::pair<const char*, const char*>); void SetCurrentRenderingBackend(uint8_t index, std::pair<const char*, const char*>);
const char** GetSupportedTextureFilters(); const char** GetSupportedTextureFilters();
void SetResolutionMultiplier(float multiplier); void SetResolutionMultiplier(float multiplier);
void SetMSAALevel(uint32_t value); void SetMSAALevel(uint32_t value);
std::vector<std::pair<const char*, const char*>> GetAvailableAudioBackends();
std::pair<const char*, const char*> GetCurrentAudioBackend();
void SetCurrentAudioBackend(uint8_t index, std::pair<const char*, const char*>);
void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled = false, bool isHidden = false); void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc, bool isEnabled = false, bool isHidden = false);
void EnableWindow(const std::string& name, bool isEnabled = true); void EnableWindow(const std::string& name, bool isEnabled = true);

View File

@ -263,6 +263,7 @@ namespace Ship {
GetConfig()->setInt("Window.Height", 480); GetConfig()->setInt("Window.Height", 480);
GetConfig()->setBool("Window.Options", false); GetConfig()->setBool("Window.Options", false);
GetConfig()->setString("Window.GfxBackend", ""); GetConfig()->setString("Window.GfxBackend", "");
GetConfig()->setString("Window.AudioBackend", "");
GetConfig()->setBool("Window.Fullscreen.Enabled", false); GetConfig()->setBool("Window.Fullscreen.Enabled", false);
GetConfig()->setInt("Window.Fullscreen.Width", 1920); GetConfig()->setInt("Window.Fullscreen.Width", 1920);
@ -283,7 +284,6 @@ namespace Ship {
InitializeConfiguration(); InitializeConfiguration();
InitializeResourceManager(); InitializeResourceManager();
CreateDefaults(); CreateDefaults();
InitializeAudioPlayer();
InitializeControlDeck(); InitializeControlDeck();
bIsFullscreen = GetConfig()->getBool("Window.Fullscreen.Enabled", false); bIsFullscreen = GetConfig()->getBool("Window.Fullscreen.Enabled", false);
@ -297,9 +297,13 @@ namespace Ship {
} }
dwMenubar = GetConfig()->getBool("Window.Options", false); dwMenubar = GetConfig()->getBool("Window.Options", false);
const std::string& gfx_backend = GetConfig()->getString("Window.GfxBackend");
gfxBackend = GetConfig()->getString("Window.GfxBackend");
InitializeWindowManager(); InitializeWindowManager();
audioBackend = GetConfig()->getString("Window.AudioBackend");
InitializeAudioPlayer();
gfx_init(WmApi, RenderingApi, GetName().c_str(), bIsFullscreen, dwWidth, dwHeight); gfx_init(WmApi, RenderingApi, GetName().c_str(), bIsFullscreen, dwWidth, dwHeight);
WmApi->set_fullscreen_changed_callback(OnFullscreenChanged); WmApi->set_fullscreen_changed_callback(OnFullscreenChanged);
WmApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp); WmApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp);
@ -442,6 +446,21 @@ namespace Ship {
#else #else
APlayer = std::make_shared<SDLAudioPlayer>(); APlayer = std::make_shared<SDLAudioPlayer>();
#endif #endif
// Config can override
#ifdef _WIN32
if (audioBackend == "wasapi") {
APlayer = std::make_shared<WasapiAudioPlayer>();
}
#endif
#if defined(__linux)
if (audioBackend == "pulse") {
APlayer = std::make_shared<PulseAudioPlayer>();
}
#endif
if (audioBackend == "sdl") {
APlayer = std::make_shared<SDLAudioPlayer>();
}
} }
void Window::InitializeWindowManager() { void Window::InitializeWindowManager() {

View File

@ -74,6 +74,7 @@ namespace Ship {
std::shared_ptr<ControlDeck> ControllerApi; std::shared_ptr<ControlDeck> ControllerApi;
std::string gfxBackend; std::string gfxBackend;
std::string audioBackend;
GfxRenderingAPI* RenderingApi; GfxRenderingAPI* RenderingApi;
GfxWindowManagerAPI* WmApi; GfxWindowManagerAPI* WmApi;
bool bIsFullscreen; bool bIsFullscreen;

View File

@ -502,6 +502,22 @@ namespace GameMenuBar {
UIWidgets::Spacer(0); UIWidgets::Spacer(0);
BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE); BindAudioSlider("Fanfare Volume: %d %%", "gFanfareVolume", 1.0f, SEQ_FANFARE);
ImGui::Text("Audio API (Needs reload)");
auto audioBackends = SohImGui::GetAvailableAudioBackends();
auto currentAudioBackend = SohImGui::GetCurrentAudioBackend();
if (ImGui::BeginCombo("##AApi", currentAudioBackend.second)) {
if (audioBackends.size() > 1) {
for (uint8_t i = 0; i < audioBackends.size(); i++) {
if (ImGui::Selectable(audioBackends[i].second, audioBackends[i] == currentAudioBackend)) {
SohImGui::SetCurrentAudioBackend(i, audioBackends[i]);
}
}
}
ImGui::EndCombo();
}
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -609,13 +625,15 @@ namespace GameMenuBar {
} }
ImGui::Text("Renderer API (Needs reload)"); ImGui::Text("Renderer API (Needs reload)");
auto backends = SohImGui::GetAvailableRenderingBackends(); auto renderingBackends = SohImGui::GetAvailableRenderingBackends();
auto currentBackend = SohImGui::GetCurrentRenderingBackend(); auto currentRenderingBackend = SohImGui::GetCurrentRenderingBackend();
if (ImGui::BeginCombo("##RApi", currentBackend.second)) { if (ImGui::BeginCombo("##RApi", currentRenderingBackend.second)) {
for (uint8_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { if (renderingBackends.size() > 1) {
if (ImGui::Selectable(backends[i].second, backends[i] == currentBackend)) { for (uint8_t i = 0; i < renderingBackends.size(); i++) {
SohImGui::SetCurrentRenderingBackend(i, backends[i]); if (ImGui::Selectable(renderingBackends[i].second, renderingBackends[i] == currentRenderingBackend)) {
SohImGui::SetCurrentRenderingBackend(i, renderingBackends[i]);
}
} }
} }