From 84c6455c953212c206517b9f4a2a5ed647bff040 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Mon, 26 Oct 2015 00:01:01 +0100 Subject: [PATCH 1/4] spu2x-sdl: add a gui setting to select the API The purpose is to workaround bug with default API Code is not ideal because SDL/gui are mixed. But it would be enough for future release. V2: ifdef SDL2 code --- plugins/spu2-x/src/Linux/Config.cpp | 41 +++++++++++++++++++++++++ plugins/spu2-x/src/SndOut_SDL.cpp | 46 ++++++++++++++++++++++++----- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/plugins/spu2-x/src/Linux/Config.cpp b/plugins/spu2-x/src/Linux/Config.cpp index a61df22fb..81c7579af 100644 --- a/plugins/spu2-x/src/Linux/Config.cpp +++ b/plugins/spu2-x/src/Linux/Config.cpp @@ -19,6 +19,9 @@ #include "Dialogs.h" #include "Config.h" +#include +#include + #ifdef PCSX2_DEVBUILD static const int LATENCY_MAX = 3000; #else @@ -70,6 +73,7 @@ u32 OutputModule = 0; int SndOutLatencyMS = 300; int SynchMode = 0; // Time Stretch, Async or Disabled static u32 OutputAPI = 0; +static u32 SdlOutputAPI = 0; int numSpeakers = 0; int dplLevel = 0; @@ -121,10 +125,21 @@ void ReadSettings() if (temp == L"OSS") OutputAPI = 1; if (temp == L"JACK") OutputAPI = 2; + CfgReadStr( L"SDL", L"HostApi", temp, L"pulseaudio" ); + SdlOutputAPI = -1; +#if SDL_MAJOR_VERSION >= 2 + // YES It sucks ... + for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) { + if (!temp.Cmp(SDL_GetAudioDriver(i))) + SdlOutputAPI = i; + } +#endif + SndOutLatencyMS = CfgReadInt(L"OUTPUT",L"Latency", 300); SynchMode = CfgReadInt( L"OUTPUT", L"Synch_Mode", 0); PortaudioOut->ReadSettings(); + SDLOut->ReadSettings(); SoundtouchCfg::ReadSettings(); DebugConfig::ReadSettings(); @@ -167,6 +182,7 @@ void WriteSettings() CfgWriteInt(L"OUTPUT",L"Synch_Mode", SynchMode); PortaudioOut->WriteSettings(); + SDLOut->WriteSettings(); SoundtouchCfg::WriteSettings(); DebugConfig::WriteSettings(); } @@ -198,6 +214,9 @@ void DisplayDialog() GtkWidget *output_frame, *output_box; GtkWidget *mod_label, *mod_box; GtkWidget *api_label, *api_box; +#if SDL_MAJOR_VERSION >= 2 + GtkWidget *sdl_api_label, *sdl_api_box; +#endif GtkWidget *latency_label, *latency_slide; GtkWidget *sync_label, *sync_box; GtkWidget *advanced_button; @@ -242,6 +261,16 @@ void DisplayDialog() gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "2 - JACK"); gtk_combo_box_set_active(GTK_COMBO_BOX(api_box), OutputAPI); +#if SDL_MAJOR_VERSION >= 2 + sdl_api_label = gtk_label_new ("SDL API:"); + sdl_api_box = gtk_combo_box_text_new (); + // YES It sucks ... + for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) { + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sdl_api_box), SDL_GetAudioDriver(i)); + } + gtk_combo_box_set_active(GTK_COMBO_BOX(sdl_api_box), SdlOutputAPI); +#endif + latency_label = gtk_label_new ("Latency:"); #if GTK_MAJOR_VERSION < 3 latency_slide = gtk_hscale_new_with_range(LATENCY_MIN, LATENCY_MAX, 5); @@ -282,6 +311,10 @@ void DisplayDialog() gtk_container_add(GTK_CONTAINER(output_box), mod_box); gtk_container_add(GTK_CONTAINER(output_box), api_label); gtk_container_add(GTK_CONTAINER(output_box), api_box); +#if SDL_MAJOR_VERSION >= 2 + gtk_container_add(GTK_CONTAINER(output_box), sdl_api_label); + gtk_container_add(GTK_CONTAINER(output_box), sdl_api_box); +#endif gtk_container_add(GTK_CONTAINER(output_box), sync_label); gtk_container_add(GTK_CONTAINER(output_box), sync_box); gtk_container_add(GTK_CONTAINER(output_box), latency_label); @@ -327,6 +360,14 @@ void DisplayDialog() } } +#if SDL_MAJOR_VERSION >= 2 + if (gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box)) != -1) { + SdlOutputAPI = gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box)); + // YES It sucks ... + SDLOut->SetApiSettings(wxString(SDL_GetAudioDriver(SdlOutputAPI))); + } +#endif + SndOutLatencyMS = gtk_range_get_value(GTK_RANGE(latency_slide)); if (gtk_combo_box_get_active(GTK_COMBO_BOX(sync_box)) != -1) diff --git a/plugins/spu2-x/src/SndOut_SDL.cpp b/plugins/spu2-x/src/SndOut_SDL.cpp index 4e3c63dad..dce06f4ec 100644 --- a/plugins/spu2-x/src/SndOut_SDL.cpp +++ b/plugins/spu2-x/src/SndOut_SDL.cpp @@ -18,6 +18,7 @@ #include "Global.h" #include "SndOut.h" +#include "Dialogs.h" #include @@ -67,8 +68,13 @@ namespace { struct SDLAudioMod : public SndOutModule { static SDLAudioMod mod; + wxString m_api; s32 Init() { + ReadSettings(); + + fprintf(stderr, "SDL audio driver is %s\n", static_cast(m_api.c_str())); + /* SDL backends will mangle the AudioSpec and change the sample count. If we reopen * the audio backend, we need to make sure we keep our desired samples in the spec */ spec.samples = desiredSamples; @@ -96,20 +102,46 @@ struct SDLAudioMod : public SndOutModule { SDL_CloseAudio(); } + ~SDLAudioMod() { Close(); } + s32 Test() const { return 0; } - void Configure(uptr parent) {} - void ReadSettings() {} - void SetApiSettings(wxString api) {} - void WriteSettings() const {}; int GetEmptySampleCount() { return 0; } - ~SDLAudioMod() { Close(); } + void Configure(uptr parent) {} + + void ReadSettings() { + wxString api(L"EMPTYEMPTYEMPTY"); + CfgReadStr(L"SDL", L"HostApi", api, L"pulseaudio"); + SetApiSettings(api); + } + + void WriteSettings() const { + CfgWriteStr(L"SDL", L"HostApi", m_api); + }; + + void SetApiSettings(wxString api) { +#if SDL_MAJOR_VERSION >= 2 + // Validate the api name + bool valid = false; + for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) { + valid |= (api.Cmp(wxString(SDL_GetAudioDriver(i))) == 0); + } + if (valid) { + m_api = api; + } else { + fprintf(stderr, "SDL audio driver configuration is invalid!\n" + "It will be replaced by pulseaudio!\n"); + m_api = "pulseaudio"; + } +#endif + } + private: SDL_AudioSpec spec; - SDLAudioMod() - : spec({SampleRate, format, channels, 0, + SDLAudioMod() : m_api("pulseaudio"), + spec({SampleRate, format, channels, 0, desiredSamples, 0, 0, &callback_fillBuffer, nullptr}) { // Number of samples must be a multiple of packet size. From 2a68c3585cd2997fa89d289350ca939601e62e35 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Mon, 26 Oct 2015 00:26:49 +0100 Subject: [PATCH 2/4] spu2x-sdl: fiddle with SDL to init the selected API Note: SDL_Init is mandatory oterwise SDL_OpenAudio will redo the init. So the only sane way is to initialize pulseaudio, close everything, and finally init the requested driver. V2: * ifdef SDL2 code V3: * use std::string for m_api (avoid issue issue with wx2.8) * call the good function to properly close subsystem avoid crashes --- plugins/spu2-x/src/SndOut_SDL.cpp | 41 +++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/plugins/spu2-x/src/SndOut_SDL.cpp b/plugins/spu2-x/src/SndOut_SDL.cpp index dce06f4ec..72b2f4981 100644 --- a/plugins/spu2-x/src/SndOut_SDL.cpp +++ b/plugins/spu2-x/src/SndOut_SDL.cpp @@ -68,21 +68,46 @@ namespace { struct SDLAudioMod : public SndOutModule { static SDLAudioMod mod; - wxString m_api; + std::string m_api; s32 Init() { ReadSettings(); - fprintf(stderr, "SDL audio driver is %s\n", static_cast(m_api.c_str())); +#if SDL_MAJOR_VERSION >= 2 + std::cerr << "Request SDL audio driver: " << m_api.c_str() << std::endl; +#endif /* SDL backends will mangle the AudioSpec and change the sample count. If we reopen * the audio backend, we need to make sure we keep our desired samples in the spec */ spec.samples = desiredSamples; - if(SDL_Init(SDL_INIT_AUDIO) < 0 || SDL_OpenAudio(&spec, NULL) < 0) { + // Mandatory otherwise, init will be redone in SDL_OpenAudio + if (SDL_Init(SDL_INIT_AUDIO) < 0) { + std::cerr << "SPU2-X: SDL INIT audio error: " << SDL_GetError() << std::endl; + return -1; + } + +#if SDL_MAJOR_VERSION >= 2 + if (m_api.compare("pulseaudio")) { + // Close the audio, but keep the subsystem open + SDL_AudioQuit(); + // Reopen the audio + if (SDL_AudioInit(m_api.c_str()) < 0) { + std::cerr << "SPU2-X: SDL audio init error: " << SDL_GetError() << std::endl; + return -1; + } + } +#endif + + if (SDL_OpenAudio(&spec, NULL) < 0) { std::cerr << "SPU2-X: SDL audio error: " << SDL_GetError() << std::endl; return -1; } + +#if SDL_MAJOR_VERSION >= 2 + std::cerr << "Opened SDL audio driver: " << SDL_GetCurrentAudioDriver() << std::endl; +#endif + /* This is so ugly. It is hilariously ugly. I didn't use a vector to save reallocs. */ if(samples != spec.samples || buffer == NULL) buffer = std::unique_ptr(new StereoOut_SDL[spec.samples]); @@ -99,7 +124,8 @@ struct SDLAudioMod : public SndOutModule { const wchar_t* GetLongName() const { return L"SDL Audio"; } void Close() { - SDL_CloseAudio(); + // Related to SDL_Init(SDL_INIT_AUDIO) + SDL_QuitSubSystem(SDL_INIT_AUDIO); } ~SDLAudioMod() { Close(); } @@ -123,14 +149,15 @@ struct SDLAudioMod : public SndOutModule { #if SDL_MAJOR_VERSION >= 2 // Validate the api name bool valid = false; + std::string api_name = std::string(api); for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) { - valid |= (api.Cmp(wxString(SDL_GetAudioDriver(i))) == 0); + valid |= (api_name.compare(SDL_GetAudioDriver(i)) == 0); } if (valid) { m_api = api; } else { - fprintf(stderr, "SDL audio driver configuration is invalid!\n" - "It will be replaced by pulseaudio!\n"); + std::cerr << "SDL audio driver configuration is invalid!" << std::endl + << "It will be replaced by pulseaudio!" << std::endl; m_api = "pulseaudio"; } #endif From 66259dee17bccd798e4a0fcc70c0d65dfef7a6a2 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 30 Oct 2015 17:12:40 +0100 Subject: [PATCH 3/4] spu2x-sdl: always use 16 bit formats 32 bits range is too big and requires to maximize the volume. --- plugins/spu2-x/src/SndOut_SDL.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/plugins/spu2-x/src/SndOut_SDL.cpp b/plugins/spu2-x/src/SndOut_SDL.cpp index 72b2f4981..c73b2ae1e 100644 --- a/plugins/spu2-x/src/SndOut_SDL.cpp +++ b/plugins/spu2-x/src/SndOut_SDL.cpp @@ -27,11 +27,7 @@ * build wx without sdl support, though) and onepad at the time of writing this. */ #include #include -#if SDL_MAJOR_VERSION >= 2 -typedef StereoOut32 StereoOut_SDL; -#else typedef StereoOut16 StereoOut_SDL; -#endif namespace { /* Since spu2 only ever outputs stereo, we don't worry about emitting surround sound @@ -42,12 +38,7 @@ namespace { * sample count and SDL may provide otherwise. Pulseaudio will cut this value in half if * PA_STREAM_ADJUST_LATENCY is set in the backened, for example. */ const Uint16 desiredSamples = 1024; - const Uint16 format = -#if SDL_MAJOR_VERSION >= 2 - AUDIO_S32SYS; -#else - AUDIO_S16SYS; -#endif + const Uint16 format = AUDIO_S16SYS; Uint16 samples = desiredSamples; From e31cb8cbcdcf62d5c5b1bc43e93d60a392dc16dd Mon Sep 17 00:00:00 2001 From: Jonathan Li Date: Sat, 31 Oct 2015 11:06:15 +0100 Subject: [PATCH 4/4] spu2x-sdl: restore WX2.8 build compilation Signed-off-by: Gregory Hainaut --- plugins/spu2-x/src/Linux/Config.cpp | 4 ++-- plugins/spu2-x/src/SndOut_SDL.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/spu2-x/src/Linux/Config.cpp b/plugins/spu2-x/src/Linux/Config.cpp index 81c7579af..87d470247 100644 --- a/plugins/spu2-x/src/Linux/Config.cpp +++ b/plugins/spu2-x/src/Linux/Config.cpp @@ -130,7 +130,7 @@ void ReadSettings() #if SDL_MAJOR_VERSION >= 2 // YES It sucks ... for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) { - if (!temp.Cmp(SDL_GetAudioDriver(i))) + if (!temp.Cmp(wxString(SDL_GetAudioDriver(i), wxConvUTF8))) SdlOutputAPI = i; } #endif @@ -364,7 +364,7 @@ void DisplayDialog() if (gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box)) != -1) { SdlOutputAPI = gtk_combo_box_get_active(GTK_COMBO_BOX(sdl_api_box)); // YES It sucks ... - SDLOut->SetApiSettings(wxString(SDL_GetAudioDriver(SdlOutputAPI))); + SDLOut->SetApiSettings(wxString(SDL_GetAudioDriver(SdlOutputAPI), wxConvUTF8)); } #endif diff --git a/plugins/spu2-x/src/SndOut_SDL.cpp b/plugins/spu2-x/src/SndOut_SDL.cpp index c73b2ae1e..246d192e1 100644 --- a/plugins/spu2-x/src/SndOut_SDL.cpp +++ b/plugins/spu2-x/src/SndOut_SDL.cpp @@ -133,19 +133,19 @@ struct SDLAudioMod : public SndOutModule { } void WriteSettings() const { - CfgWriteStr(L"SDL", L"HostApi", m_api); + CfgWriteStr(L"SDL", L"HostApi", wxString(m_api.c_str(), wxConvUTF8)); }; void SetApiSettings(wxString api) { #if SDL_MAJOR_VERSION >= 2 // Validate the api name bool valid = false; - std::string api_name = std::string(api); + std::string api_name = std::string(api.utf8_str()); for (int i = 0; i < SDL_GetNumAudioDrivers(); ++i) { valid |= (api_name.compare(SDL_GetAudioDriver(i)) == 0); } if (valid) { - m_api = api; + m_api = api.utf8_str(); } else { std::cerr << "SDL audio driver configuration is invalid!" << std::endl << "It will be replaced by pulseaudio!" << std::endl;