mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
SDL: Add UI to reset audio device at runtime.
This commit is contained in:
parent
8751316051
commit
c30bc4ee7d
5 changed files with 164 additions and 79 deletions
113
Qt/QtMain.cpp
113
Qt/QtMain.cpp
|
@ -29,9 +29,7 @@
|
|||
#ifdef SDL
|
||||
#include "SDL/SDLJoystick.h"
|
||||
#include "SDL_audio.h"
|
||||
#define MainAudioDeviceID SDL_AudioDeviceID
|
||||
#endif
|
||||
#define MainAudioDeviceID int
|
||||
#include "QtMain.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "i18n/i18n.h"
|
||||
|
@ -49,9 +47,55 @@ static int browseFileEvent = -1;
|
|||
static int browseFolderEvent = -1;
|
||||
|
||||
#ifdef SDL
|
||||
static SDL_AudioDeviceID audioDev = 0;
|
||||
|
||||
extern void mixaudio(void *userdata, Uint8 *stream, int len) {
|
||||
NativeMix((short *)stream, len / 4);
|
||||
}
|
||||
|
||||
static void InitSDLAudioDevice() {
|
||||
SDL_AudioSpec fmt, ret_fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.freq = 44100;
|
||||
fmt.format = AUDIO_S16;
|
||||
fmt.channels = 2;
|
||||
fmt.samples = 2048;
|
||||
fmt.callback = &mixaudio;
|
||||
fmt.userdata = nullptr;
|
||||
|
||||
audioDev = 0;
|
||||
if (!g_Config.sAudioDevice.empty()) {
|
||||
audioDev = SDL_OpenAudioDevice(g_Config.sAudioDevice.c_str(), 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (audioDev <= 0) {
|
||||
WLOG("Failed to open preferred audio device %s", g_Config.sAudioDevice.c_str());
|
||||
}
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
ELOG("Failed to open audio: %s", SDL_GetError());
|
||||
} else {
|
||||
if (ret_fmt.samples != fmt.samples) // Notify, but still use it
|
||||
ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples);
|
||||
if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) {
|
||||
ELOG("Sound buffer format does not match requested format.");
|
||||
ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq);
|
||||
ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format);
|
||||
ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels);
|
||||
ELOG("Provided output format does not match requirement, turning audio off");
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
SDL_PauseAudioDevice(audioDev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void StopSDLAudioDevice() {
|
||||
if (audioDev > 0) {
|
||||
SDL_PauseAudioDevice(audioDev, 1);
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string System_GetProperty(SystemProperty prop) {
|
||||
|
@ -72,6 +116,26 @@ std::string System_GetProperty(SystemProperty prop) {
|
|||
return QLocale::system().name().toStdString();
|
||||
case SYSPROP_CLIPBOARD_TEXT:
|
||||
return QApplication::clipboard()->text().toStdString();
|
||||
#if defined(SDL)
|
||||
case SYSPROP_AUDIO_DEVICE_LIST:
|
||||
{
|
||||
std::string result;
|
||||
for (int i = 0; i < SDL_GetNumAudioDevices(0); ++i) {
|
||||
const char *name = SDL_GetAudioDeviceName(i, 0);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
result = name;
|
||||
} else {
|
||||
result.append(1, '\0');
|
||||
result.append(name);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
@ -129,6 +193,11 @@ void System_SendMessage(const char *command, const char *parameter) {
|
|||
qApp->exit(0);
|
||||
} else if (!strcmp(command, "setclipboardtext")) {
|
||||
QApplication::clipboard()->setText(parameter);
|
||||
#if defined(SDL)
|
||||
} else if (!strcmp(command, "audio_resetDevice")) {
|
||||
StopSDLAudioDevice();
|
||||
InitSDLAudioDevice();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,7 +239,7 @@ float CalculateDPIScale()
|
|||
#endif
|
||||
}
|
||||
|
||||
static int mainInternal(QApplication &a, MainAudioDeviceID &audioDev) {
|
||||
static int mainInternal(QApplication &a) {
|
||||
#ifdef MOBILE_DEVICE
|
||||
emugl = new MainUI();
|
||||
emugl->resize(pixel_xres, pixel_yres);
|
||||
|
@ -187,40 +256,7 @@ static int mainInternal(QApplication &a, MainAudioDeviceID &audioDev) {
|
|||
SDLJoystick joy(true);
|
||||
joy.registerEventHandler();
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
SDL_AudioSpec fmt, ret_fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.freq = 44100;
|
||||
fmt.format = AUDIO_S16;
|
||||
fmt.channels = 2;
|
||||
fmt.samples = 2048;
|
||||
fmt.callback = &mixaudio;
|
||||
fmt.userdata = (void *)0;
|
||||
|
||||
audioDev = 0;
|
||||
if (!g_Config.sAudioDevice.empty()) {
|
||||
audioDev = SDL_OpenAudioDevice(g_Config.sAudioDevice.c_str(), 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (audioDev <= 0) {
|
||||
WLOG("Failed to open preferred audio device %s", g_Config.sAudioDevice.c_str());
|
||||
}
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
ELOG("Failed to open audio: %s", SDL_GetError());
|
||||
} else {
|
||||
if (ret_fmt.samples != fmt.samples) // Notify, but still use it
|
||||
ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples);
|
||||
if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) {
|
||||
ELOG("Sound buffer format does not match requested format.");
|
||||
ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq);
|
||||
ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format);
|
||||
ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels);
|
||||
ELOG("Provided output format does not match requirement, turning audio off");
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
SDL_PauseAudioDevice(audioDev, 0);
|
||||
}
|
||||
InitSDLAudioDevice();
|
||||
#else
|
||||
QScopedPointer<MainAudio> audio(new MainAudio());
|
||||
audio->run();
|
||||
|
@ -620,8 +656,7 @@ int main(int argc, char *argv[])
|
|||
// TODO: Support other backends than GL, like Vulkan, in the Qt backend.
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
|
||||
MainAudioDeviceID audioDev = 0;
|
||||
int ret = mainInternal(a, audioDev);
|
||||
int ret = mainInternal(a);
|
||||
ILOG("Left mainInternal here.");
|
||||
|
||||
#ifdef SDL
|
||||
|
|
113
SDL/SDLMain.cpp
113
SDL/SDLMain.cpp
|
@ -81,6 +81,57 @@ int getDisplayNumber(void) {
|
|||
return displayNumber;
|
||||
}
|
||||
|
||||
extern void mixaudio(void *userdata, Uint8 *stream, int len) {
|
||||
NativeMix((short *)stream, len / 4);
|
||||
}
|
||||
|
||||
static SDL_AudioDeviceID audioDev = 0;
|
||||
|
||||
// Must be called after NativeInit().
|
||||
static void InitSDLAudioDevice() {
|
||||
SDL_AudioSpec fmt, ret_fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.freq = 44100;
|
||||
fmt.format = AUDIO_S16;
|
||||
fmt.channels = 2;
|
||||
fmt.samples = 2048;
|
||||
fmt.callback = &mixaudio;
|
||||
fmt.userdata = nullptr;
|
||||
|
||||
audioDev = 0;
|
||||
if (!g_Config.sAudioDevice.empty()) {
|
||||
audioDev = SDL_OpenAudioDevice(g_Config.sAudioDevice.c_str(), 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (audioDev <= 0) {
|
||||
WLOG("Failed to open preferred audio device %s", g_Config.sAudioDevice.c_str());
|
||||
}
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
ELOG("Failed to open audio: %s", SDL_GetError());
|
||||
} else {
|
||||
if (ret_fmt.samples != fmt.samples) // Notify, but still use it
|
||||
ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples);
|
||||
if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) {
|
||||
ELOG("Sound buffer format does not match requested format.");
|
||||
ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq);
|
||||
ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format);
|
||||
ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels);
|
||||
ELOG("Provided output format does not match requirement, turning audio off");
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
SDL_PauseAudioDevice(audioDev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void StopSDLAudioDevice() {
|
||||
if (audioDev > 0) {
|
||||
SDL_PauseAudioDevice(audioDev, 1);
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
}
|
||||
|
||||
// Simple implementations of System functions
|
||||
|
||||
|
||||
|
@ -120,6 +171,9 @@ void System_SendMessage(const char *command, const char *parameter) {
|
|||
g_QuitRequested = true;
|
||||
} else if (!strcmp(command, "setclipboardtext")) {
|
||||
SDL_SetClipboardText(parameter);
|
||||
} else if (!strcmp(command, "audio_resetDevice")) {
|
||||
StopSDLAudioDevice();
|
||||
InitSDLAudioDevice();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,6 +275,24 @@ std::string System_GetProperty(SystemProperty prop) {
|
|||
}
|
||||
case SYSPROP_CLIPBOARD_TEXT:
|
||||
return SDL_HasClipboardText() ? SDL_GetClipboardText() : "";
|
||||
case SYSPROP_AUDIO_DEVICE_LIST:
|
||||
{
|
||||
std::string result;
|
||||
for (int i = 0; i < SDL_GetNumAudioDevices(0); ++i) {
|
||||
const char *name = SDL_GetAudioDeviceName(i, 0);
|
||||
if (!name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
result = name;
|
||||
} else {
|
||||
result.append(1, '\0');
|
||||
result.append(name);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
@ -258,10 +330,6 @@ bool System_GetPropertyBool(SystemProperty prop) {
|
|||
}
|
||||
}
|
||||
|
||||
extern void mixaudio(void *userdata, Uint8 *stream, int len) {
|
||||
NativeMix((short *)stream, len / 4);
|
||||
}
|
||||
|
||||
// returns -1 on failure
|
||||
static int parseInt(const char *str) {
|
||||
int val;
|
||||
|
@ -573,42 +641,7 @@ int main(int argc, char *argv[]) {
|
|||
// Ensure that the swap interval is set after context creation (needed for kmsdrm)
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
|
||||
SDL_AudioSpec fmt, ret_fmt;
|
||||
memset(&fmt, 0, sizeof(fmt));
|
||||
fmt.freq = 44100;
|
||||
fmt.format = AUDIO_S16;
|
||||
fmt.channels = 2;
|
||||
fmt.samples = 2048;
|
||||
fmt.callback = &mixaudio;
|
||||
fmt.userdata = (void *)0;
|
||||
|
||||
SDL_AudioDeviceID audioDev = 0;
|
||||
if (!g_Config.sAudioDevice.empty()) {
|
||||
audioDev = SDL_OpenAudioDevice(g_Config.sAudioDevice.c_str(), 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (audioDev <= 0) {
|
||||
WLOG("Failed to open preferred audio device %s", g_Config.sAudioDevice.c_str());
|
||||
}
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
}
|
||||
if (audioDev <= 0) {
|
||||
ELOG("Failed to open audio: %s", SDL_GetError());
|
||||
} else {
|
||||
if (ret_fmt.samples != fmt.samples) // Notify, but still use it
|
||||
ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples);
|
||||
if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) {
|
||||
ELOG("Sound buffer format does not match requested format.");
|
||||
ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq);
|
||||
ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format);
|
||||
ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels);
|
||||
ELOG("Provided output format does not match requirement, turning audio off");
|
||||
SDL_CloseAudioDevice(audioDev);
|
||||
}
|
||||
|
||||
// Audio must be unpaused _after_ NativeInit()
|
||||
SDL_PauseAudioDevice(audioDev, 0);
|
||||
}
|
||||
InitSDLAudioDevice();
|
||||
|
||||
if (joystick_enabled) {
|
||||
joystick = new SDLJoystick();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "base/display.h" // Only to check screen aspect ratio with pixel_yres/pixel_xres
|
||||
|
||||
#include "base/colorutil.h"
|
||||
#include "base/stringutil.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "math/curves.h"
|
||||
#include "net/resolve.h"
|
||||
|
@ -491,6 +492,13 @@ void GameSettingsScreen::CreateViews() {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(SDL)
|
||||
std::vector<std::string> audioDeviceList;
|
||||
SplitString(System_GetProperty(SYSPROP_AUDIO_DEVICE_LIST), '\0', audioDeviceList);
|
||||
PopupMultiChoiceDynamic *audioDevice = audioSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sAudioDevice, a->T("Device"), audioDeviceList, nullptr, screenManager()));
|
||||
audioDevice->OnChoice.Handle(this, &GameSettingsScreen::OnAudioDevice);
|
||||
#endif
|
||||
|
||||
static const char *latency[] = { "Low", "Medium", "High" };
|
||||
PopupMultiChoice *lowAudio = audioSettings->Add(new PopupMultiChoice(&g_Config.iAudioLatency, a->T("Audio Latency"), latency, 0, ARRAY_SIZE(latency), gr->GetName(), screenManager()));
|
||||
lowAudio->SetEnabledPtr(&g_Config.bEnableSound);
|
||||
|
@ -1180,6 +1188,11 @@ UI::EventReturn GameSettingsScreen::OnRenderingDevice(UI::EventParams &e) {
|
|||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) {
|
||||
System_SendMessage("audio_resetDevice", "");
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) {
|
||||
#if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI)
|
||||
const size_t name_len = 256;
|
||||
|
|
|
@ -97,6 +97,7 @@ private:
|
|||
UI::EventReturn OnRenderingMode(UI::EventParams &e);
|
||||
UI::EventReturn OnRenderingBackend(UI::EventParams &e);
|
||||
UI::EventReturn OnRenderingDevice(UI::EventParams &e);
|
||||
UI::EventReturn OnAudioDevice(UI::EventParams &e);
|
||||
UI::EventReturn OnJitAffectingSetting(UI::EventParams &e);
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
UI::EventReturn OnChangeMemStickDir(UI::EventParams &e);
|
||||
|
|
|
@ -163,6 +163,9 @@ enum SystemProperty {
|
|||
SYSPROP_AUDIO_OPTIMAL_SAMPLE_RATE,
|
||||
SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER,
|
||||
|
||||
// Exposed on SDL.
|
||||
SYSPROP_AUDIO_DEVICE_LIST,
|
||||
|
||||
SYSPROP_SUPPORTS_PERMISSIONS,
|
||||
SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE,
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue