mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Merge pull request #21623 from hrydgard/more-ui-improvements
Misc fixes
This commit is contained in:
6 files changed
+236
-198
No files matched your search
@@ -726,7 +726,8 @@ void AdhocServerScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
|
||||
CollapsibleSection *publicSection = innerView->Add(new CollapsibleSection(n->T("Public server list"), new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
for (const auto &entry : entries) {
|
||||
if (entry.hidden)
|
||||
// Show even hidden entries, as long as they are chosen currently.
|
||||
if (entry.hidden && entry.host != g_Config.sProAdhocServer)
|
||||
continue;
|
||||
AddButtonFromEntry(publicSection, entry, false);
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ void DeveloperToolsScreen::CreateGeneralTab(UI::LinearLayout *list) {
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(IOS)
|
||||
list->Add(new NoticeView(NoticeLevel::WARN, ms->T("Moving the memstick directory is NOT recommended on iOS"), ""));
|
||||
list->Add(new NoticeView(NoticeLevel::WARN, ms->T("Moving the memstick directory is NOT recommended on iOS"), ""))->SetWrapText(true);
|
||||
list->Add(new Choice(sy->T("Set Memory Stick folder")))->OnClick.Add(
|
||||
[=](UI::EventParams &) {
|
||||
SetMemStickDirDarwin(GetRequesterToken());
|
||||
|
||||
@@ -1851,7 +1851,12 @@ ScreenRenderFlags EmuScreen::RunEmulation(bool skipBufferEffects) {
|
||||
|
||||
void EmuScreen::runImDebugger() {
|
||||
if (!lastImguiEnabled_ && g_Config.bShowImDebugger) {
|
||||
#if !defined(MOBILE_DEVICE)
|
||||
// On mobile devices (specifically iOS) we don't want to pop the keyboard
|
||||
// on activating imgui. Instead, we should do it when a text edit field in imgui gets focus,
|
||||
// although we'll still have ugly overlap problems.
|
||||
System_NotifyUIEvent(UIEventNotification::TEXT_GOTFOCUS);
|
||||
#endif
|
||||
VERBOSE_LOG(Log::System, "activating keyboard");
|
||||
} else if (lastImguiEnabled_ && !g_Config.bShowImDebugger) {
|
||||
System_NotifyUIEvent(UIEventNotification::TEXT_LOSTFOCUS);
|
||||
|
||||
+220
-196
@@ -150,6 +150,218 @@ void WASAPIContext::ClearErrorString() {
|
||||
errorString_.clear();
|
||||
}
|
||||
|
||||
bool WASAPIContext::TryInitAudioClient3(IMMDevice *device, LatencyMode latencyMode) {
|
||||
HRESULT hr = E_FAIL;
|
||||
// Try IAudioClient3 first if not in "safe" mode. It's probably safe anyway, but still, let's use the legacy client as a safe fallback option.
|
||||
if (latencyMode != LatencyMode::Safe) {
|
||||
hr = device->Activate(__uuidof(IAudioClient3), CLSCTX_ALL, nullptr, (void**)&audioClient3_);
|
||||
} else {
|
||||
// Proceed to AudioClient.
|
||||
INFO_LOG(Log::Audio, "LatencyMode::Safe is set, skipping AudioClient3 and going directly to AudioClient");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SUCCEEDED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient3_->GetMixFormat(&format_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
SetErrorString("AudioClient3 GetMixFormat failed", hr);
|
||||
return false;
|
||||
}
|
||||
curSamplesPerSec_ = format_->nSamplesPerSec;
|
||||
|
||||
// We only use AudioClient3 if we got the format we wanted (stereo float).
|
||||
if (format_->nChannels != 2 || Classify(format_) != AudioFormat::Float) {
|
||||
// Let's fall back to the old path. The docs seem to be wrong, if you try to create an
|
||||
// AudioClient3 with low latency audio with AUTOCONVERTPCM, you get the error 0x88890021.
|
||||
INFO_LOG(Log::Audio, "AudioClient3: Got %d channels or non-float format, falling back to AudioClient", format_->nChannels);
|
||||
audioClient3_.Reset();
|
||||
// Free the format before falling through - AudioClient will allocate a new one
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
return false;
|
||||
} else {
|
||||
hr = audioClient3_->GetSharedModeEnginePeriod(format_, &defaultPeriodFrames_, &fundamentalPeriodFrames_, &minPeriodFrames_, &maxPeriodFrames_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 GetSharedModeEnginePeriod failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(Log::Audio, "AudioClient3: default: %d fundamental: %d min: %d max: %d\n", (int)defaultPeriodFrames_, (int)fundamentalPeriodFrames_, (int)minPeriodFrames_, (int)maxPeriodFrames_);
|
||||
INFO_LOG(Log::Audio, "initializing with %d frame period at %d Hz, meaning %0.1fms\n", (int)minPeriodFrames_, (int)format_->nSamplesPerSec, FramesToMs(minPeriodFrames_, format_->nSamplesPerSec));
|
||||
|
||||
hr = audioClient3_->InitializeSharedAudioStream(
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||
minPeriodFrames_,
|
||||
format_,
|
||||
nullptr
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
WARN_LOG(Log::Audio, "Error initializing AudioClient3 shared audio stream: %08lx", hr);
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 init failed", hr);
|
||||
return false;
|
||||
}
|
||||
actualPeriodFrames_ = minPeriodFrames_;
|
||||
|
||||
hr = audioClient3_->GetBufferSize(&reportedBufferSize_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 GetBufferSize failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient3_->SetEventHandle(audioEvent_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 SetEventHandle failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient3_->GetService(IID_PPV_ARGS(&renderClient_));
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 GetService failed", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WASAPIContext::TryInitAudioClient(IMMDevice *device, LatencyMode latencyMode) {
|
||||
// Fallback to IAudioClient (older OS)
|
||||
HRESULT hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&audioClient_);
|
||||
if (FAILED(hr)) {
|
||||
SetErrorString("Failed to activate audio device", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient_->GetMixFormat(&format_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
SetErrorString("AudioClient GetMixFormat failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are too many channels, try asking for a 2-channel output format.
|
||||
DWORD extraStreamFlags = 0;
|
||||
const AudioFormat fmt = Classify(format_);
|
||||
|
||||
curSamplesPerSec_ = format_->nSamplesPerSec;
|
||||
|
||||
bool createBuffer = false;
|
||||
if (fmt == AudioFormat::Float) {
|
||||
if (format_->nChannels != 2) {
|
||||
INFO_LOG(Log::Audio, "Got %d channels, asking for stereo instead", format_->nChannels);
|
||||
WAVEFORMATEXTENSIBLE stereo;
|
||||
BuildStereoFloatFormat((const WAVEFORMATEXTENSIBLE *)format_, &stereo);
|
||||
|
||||
WAVEFORMATEX *closestMatch = nullptr;
|
||||
const HRESULT result = audioClient_->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, (const WAVEFORMATEX *)&stereo, &closestMatch);
|
||||
if (result == S_OK) {
|
||||
// We got the format! Use it and set as current.
|
||||
_dbg_assert_(!closestMatch);
|
||||
WAVEFORMATEX *newFormat = (WAVEFORMATEX *)CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
|
||||
_dbg_assert_(newFormat);
|
||||
memcpy(newFormat, &stereo, sizeof(WAVEFORMATEX) + stereo.Format.cbSize);
|
||||
CoTaskMemFree(format_);
|
||||
format_ = newFormat;
|
||||
extraStreamFlags = AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||
INFO_LOG(Log::Audio, "Successfully asked for two channels");
|
||||
} else if (result == S_FALSE) {
|
||||
// We got another format. Meh, let's just use what we got.
|
||||
if (closestMatch) {
|
||||
WARN_LOG(Log::Audio, "Didn't get the format we wanted, but got: %lu ch=%d", closestMatch->nSamplesPerSec, closestMatch->nChannels);
|
||||
CoTaskMemFree(closestMatch);
|
||||
} else {
|
||||
WARN_LOG(Log::Audio, "Failed to fall back to two channels. Using workarounds.");
|
||||
}
|
||||
createBuffer = true;
|
||||
} else {
|
||||
WARN_LOG(Log::Audio, "Got other error %08lx", result);
|
||||
_dbg_assert_(!closestMatch);
|
||||
}
|
||||
} else {
|
||||
// All good, nothing to convert.
|
||||
_dbg_assert_(format_);
|
||||
}
|
||||
} else {
|
||||
// Some other format.
|
||||
WARN_LOG(Log::Audio, "Format not float, applying conversion.");
|
||||
createBuffer = true;
|
||||
}
|
||||
|
||||
// Get engine period info
|
||||
REFERENCE_TIME defaultPeriod = 0, minPeriod = 0;
|
||||
audioClient_->GetDevicePeriod(&defaultPeriod, &minPeriod);
|
||||
|
||||
const REFERENCE_TIME duration = minPeriod;
|
||||
hr = audioClient_->Initialize(
|
||||
AUDCLNT_SHAREMODE_SHARED,
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | extraStreamFlags,
|
||||
duration, // This is a minimum, the result might be larger. We use GetBufferSize to check.
|
||||
0, // ref duration, always 0 in shared mode.
|
||||
format_,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient init failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient_->GetBufferSize(&reportedBufferSize_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient GetBufferSize failed", hr);
|
||||
return false;
|
||||
}
|
||||
actualPeriodFrames_ = reportedBufferSize_; // we don't have a better estimate.
|
||||
|
||||
hr = audioClient_->SetEventHandle(audioEvent_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient SetEventHandle failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient_->GetService(IID_PPV_ARGS(&renderClient_));
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient GetService failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (createBuffer) {
|
||||
tempBuf_ = std::make_unique<float[]>(reportedBufferSize_ * 2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WASAPIContext::InitOutputDevice(std::string_view uniqueId, LatencyMode latencyMode, bool *revertedToDefault) {
|
||||
Stop();
|
||||
|
||||
@@ -189,207 +401,19 @@ bool WASAPIContext::InitOutputDevice(std::string_view uniqueId, LatencyMode late
|
||||
curDeviceName_ = desc.name;
|
||||
}
|
||||
|
||||
HRESULT hr = E_FAIL;
|
||||
// Try IAudioClient3 first if not in "safe" mode. It's probably safe anyway, but still, let's use the legacy client as a safe fallback option.
|
||||
if (latencyMode != LatencyMode::Safe) {
|
||||
hr = device->Activate(__uuidof(IAudioClient3), CLSCTX_ALL, nullptr, (void**)&audioClient3_);
|
||||
}
|
||||
|
||||
// Get rid of any old tempBuf_.
|
||||
tempBuf_.reset();
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = audioClient3_->GetMixFormat(&format_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
SetErrorString("AudioClient3 GetMixFormat failed", hr);
|
||||
// This is used by both paths.
|
||||
audioEvent_ = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
if (!TryInitAudioClient3(device.Get(), latencyMode)) {
|
||||
if (!TryInitAudioClient(device.Get(), latencyMode)) {
|
||||
// Failed both client types.
|
||||
CloseHandle(audioEvent_);
|
||||
audioEvent_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
curSamplesPerSec_ = format_->nSamplesPerSec;
|
||||
|
||||
// We only use AudioClient3 if we got the format we wanted (stereo float).
|
||||
if (format_->nChannels != 2 || Classify(format_) != AudioFormat::Float) {
|
||||
// Let's fall back to the old path. The docs seem to be wrong, if you try to create an
|
||||
// AudioClient3 with low latency audio with AUTOCONVERTPCM, you get the error 0x88890021.
|
||||
INFO_LOG(Log::Audio, "AudioClient3: Got %d channels or non-float format, falling back to AudioClient", format_->nChannels);
|
||||
audioClient3_.Reset();
|
||||
// Free the format before falling through - AudioClient will allocate a new one
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
// Fall through to AudioClient creation below.
|
||||
} else {
|
||||
hr = audioClient3_->GetSharedModeEnginePeriod(format_, &defaultPeriodFrames_, &fundamentalPeriodFrames_, &minPeriodFrames_, &maxPeriodFrames_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 GetSharedModeEnginePeriod failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(Log::Audio, "AudioClient3: default: %d fundamental: %d min: %d max: %d\n", (int)defaultPeriodFrames_, (int)fundamentalPeriodFrames_, (int)minPeriodFrames_, (int)maxPeriodFrames_);
|
||||
INFO_LOG(Log::Audio, "initializing with %d frame period at %d Hz, meaning %0.1fms\n", (int)minPeriodFrames_, (int)format_->nSamplesPerSec, FramesToMs(minPeriodFrames_, format_->nSamplesPerSec));
|
||||
|
||||
audioEvent_ = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
HRESULT result = audioClient3_->InitializeSharedAudioStream(
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
|
||||
minPeriodFrames_,
|
||||
format_,
|
||||
nullptr
|
||||
);
|
||||
if (FAILED(result)) {
|
||||
WARN_LOG(Log::Audio, "Error initializing AudioClient3 shared audio stream: %08lx", result);
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 init failed", hr);
|
||||
return false;
|
||||
}
|
||||
actualPeriodFrames_ = minPeriodFrames_;
|
||||
|
||||
hr = audioClient3_->GetBufferSize(&reportedBufferSize_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 GetBufferSize failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient3_->SetEventHandle(audioEvent_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 SetEventHandle failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient3_->GetService(IID_PPV_ARGS(&renderClient_));
|
||||
if (FAILED(hr)) {
|
||||
audioClient3_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient3 GetService failed", hr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!audioClient3_) {
|
||||
// Fallback to IAudioClient (older OS)
|
||||
HRESULT hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, nullptr, (void**)&audioClient_);
|
||||
if (FAILED(hr)) {
|
||||
SetErrorString("Failed to activate audio device", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient_->GetMixFormat(&format_);
|
||||
if (FAILED(hr)) {
|
||||
_dbg_assert_(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are too many channels, try asking for a 2-channel output format.
|
||||
DWORD extraStreamFlags = 0;
|
||||
const AudioFormat fmt = Classify(format_);
|
||||
|
||||
curSamplesPerSec_ = format_->nSamplesPerSec;
|
||||
|
||||
bool createBuffer = false;
|
||||
if (fmt == AudioFormat::Float) {
|
||||
if (format_->nChannels != 2) {
|
||||
INFO_LOG(Log::Audio, "Got %d channels, asking for stereo instead", format_->nChannels);
|
||||
WAVEFORMATEXTENSIBLE stereo;
|
||||
BuildStereoFloatFormat((const WAVEFORMATEXTENSIBLE *)format_, &stereo);
|
||||
|
||||
WAVEFORMATEX *closestMatch = nullptr;
|
||||
const HRESULT result = audioClient_->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, (const WAVEFORMATEX *)&stereo, &closestMatch);
|
||||
if (result == S_OK) {
|
||||
// We got the format! Use it and set as current.
|
||||
_dbg_assert_(!closestMatch);
|
||||
format_ = (WAVEFORMATEX *)CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
|
||||
memcpy(format_, &stereo, sizeof(WAVEFORMATEX) + stereo.Format.cbSize);
|
||||
extraStreamFlags = AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY;
|
||||
INFO_LOG(Log::Audio, "Successfully asked for two channels");
|
||||
} else if (result == S_FALSE) {
|
||||
// We got another format. Meh, let's just use what we got.
|
||||
if (closestMatch) {
|
||||
WARN_LOG(Log::Audio, "Didn't get the format we wanted, but got: %lu ch=%d", closestMatch->nSamplesPerSec, closestMatch->nChannels);
|
||||
CoTaskMemFree(closestMatch);
|
||||
} else {
|
||||
WARN_LOG(Log::Audio, "Failed to fall back to two channels. Using workarounds.");
|
||||
}
|
||||
createBuffer = true;
|
||||
} else {
|
||||
WARN_LOG(Log::Audio, "Got other error %08lx", result);
|
||||
_dbg_assert_(!closestMatch);
|
||||
}
|
||||
} else {
|
||||
// All good, nothing to convert.
|
||||
_dbg_assert_(format_);
|
||||
}
|
||||
} else {
|
||||
// Some other format.
|
||||
WARN_LOG(Log::Audio, "Format not float, applying conversion.");
|
||||
createBuffer = true;
|
||||
}
|
||||
|
||||
// Get engine period info
|
||||
REFERENCE_TIME defaultPeriod = 0, minPeriod = 0;
|
||||
audioClient_->GetDevicePeriod(&defaultPeriod, &minPeriod);
|
||||
|
||||
audioEvent_ = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
|
||||
const REFERENCE_TIME duration = minPeriod;
|
||||
hr = audioClient_->Initialize(
|
||||
AUDCLNT_SHAREMODE_SHARED,
|
||||
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | extraStreamFlags,
|
||||
duration, // This is a minimum, the result might be larger. We use GetBufferSize to check.
|
||||
0, // ref duration, always 0 in shared mode.
|
||||
format_,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient init failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient_->GetBufferSize(&reportedBufferSize_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient GetBufferSize failed", hr);
|
||||
return false;
|
||||
}
|
||||
actualPeriodFrames_ = reportedBufferSize_; // we don't have a better estimate.
|
||||
|
||||
hr = audioClient_->SetEventHandle(audioEvent_);
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient SetEventHandle failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = audioClient_->GetService(IID_PPV_ARGS(&renderClient_));
|
||||
if (FAILED(hr)) {
|
||||
audioClient_.Reset();
|
||||
CoTaskMemFree(format_);
|
||||
format_ = nullptr;
|
||||
SetErrorString("AudioClient GetService failed", hr);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (createBuffer) {
|
||||
tempBuf_ = std::make_unique<float[]>(reportedBufferSize_ * 2);
|
||||
}
|
||||
}
|
||||
|
||||
latencyMode_ = latencyMode;
|
||||
|
||||
@@ -79,6 +79,9 @@ private:
|
||||
void SetErrorString(std::string_view str, HRESULT hr);
|
||||
void ClearErrorString();
|
||||
|
||||
bool TryInitAudioClient3(IMMDevice *device, LatencyMode latencyMode);
|
||||
bool TryInitAudioClient(IMMDevice *device, LatencyMode latencyMode);
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
|
||||
@@ -1244,6 +1244,11 @@ ULUS10186 = true
|
||||
# Fortix (#20436)
|
||||
NPUZ00016 = true
|
||||
NPEZ00096 = true
|
||||
# Jetpack Joyride
|
||||
NPEZ00444 = true
|
||||
NPEZ00469 = true
|
||||
NPUZ00292 = true
|
||||
NPEZ00470 = true
|
||||
|
||||
[MemstickFixedFree]
|
||||
# Assassin's Creed : Bloodlines - issue #12761
|
||||
|
||||
Reference in new issue
Block a user