feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")

View file

@ -39,6 +39,9 @@
#include <functiondiscoverykeys.h>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
// Define IAudioClient3 if not already defined by MinGW headers
#if defined __MINGW32__ || defined __MINGW64__
@ -52,6 +55,7 @@ typedef interface IAudioClient3 IAudioClient3;
#ifndef __IAudioClient3_INTERFACE_DEFINED__
#define __IAudioClient3_INTERFACE_DEFINED__
// clang-format off
MIDL_INTERFACE("7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42")
IAudioClient3 : public IAudioClient2 {
public:
@ -83,13 +87,14 @@ public:
/* [annotation][in] */
_In_opt_ LPCGUID AudioSessionGuid) = 0;
};
// clang-format on
__CRT_UUID_DECL(IAudioClient3, 0x7ED4EE07, 0x8E67, 0x4CD4, 0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42)
#endif // __IAudioClient3_INTERFACE_DEFINED__
#endif // __MINGW32__ || __MINGW64__
#ifndef PKEY_Device_FriendlyName
#ifndef PKEY_Device_FriendlyNameGodot
#undef DEFINE_PROPERTYKEY
/* clang-format off */
@ -97,7 +102,7 @@ __CRT_UUID_DECL(IAudioClient3, 0x7ED4EE07, 0x8E67, 0x4CD4, 0x8C, 0x1A, 0x2B, 0x7
const PROPERTYKEY id = { { a, b, c, { d, e, f, g, h, i, j, k, } }, l };
/* clang-format on */
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyNameGodot, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 14);
#endif
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
@ -107,6 +112,12 @@ const IID IID_IAudioClient3 = __uuidof(IAudioClient3);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
#define SAFE_RELEASE(memory) \
if ((memory) != nullptr) { \
(memory)->Release(); \
(memory) = nullptr; \
}
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000
@ -114,6 +125,8 @@ const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
static bool default_output_device_changed = false;
static bool default_input_device_changed = false;
static int output_reinit_countdown = 0;
static int input_reinit_countdown = 0;
// Silence warning due to a COM API weirdness (GH-35194).
#if defined(__GNUC__) && !defined(__clang__)
@ -125,6 +138,8 @@ class CMMNotificationClient : public IMMNotificationClient {
LONG _cRef = 1;
public:
ComPtr<IMMDeviceEnumerator> enumerator = nullptr;
CMMNotificationClient() {}
virtual ~CMMNotificationClient() {}
@ -190,6 +205,9 @@ public:
static CMMNotificationClient notif_client;
Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_input, bool p_reinit, bool p_no_audio_client_3) {
// This function can be called recursively, so clean up before starting:
audio_device_finish(p_device);
WAVEFORMATEX *pwfex;
ComPtr<IMMDeviceEnumerator> enumerator = nullptr;
ComPtr<IMMDevice> output_device = nullptr;
@ -216,21 +234,25 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
ComPtr<IMMDevice> tmp_device = nullptr;
hr = devices->Item(i, &tmp_device);
ERR_BREAK(hr != S_OK);
ERR_BREAK_MSG(hr != S_OK, "Cannot get devices item.");
ComPtr<IPropertyStore> props = nullptr;
hr = tmp_device->OpenPropertyStore(STGM_READ, &props);
ERR_BREAK(hr != S_OK);
ERR_BREAK_MSG(hr != S_OK, "Cannot open property store.");
PROPVARIANT propvar;
PropVariantInit(&propvar);
hr = props->GetValue(PKEY_Device_FriendlyName, &propvar);
ERR_BREAK(hr != S_OK);
hr = props->GetValue(PKEY_Device_FriendlyNameGodot, &propvar);
ERR_BREAK_MSG(hr != S_OK, "Cannot get value.");
if (p_device->device_name == String(propvar.pwszVal)) {
hr = tmp_device->GetId(&strId);
ERR_BREAK(hr != S_OK);
if (unlikely(hr != S_OK)) {
PropVariantClear(&propvar);
ERR_PRINT("Cannot get device ID string.");
break;
}
found = true;
}
@ -261,9 +283,14 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
}
if (notif_client.enumerator != nullptr) {
notif_client.enumerator->UnregisterEndpointNotificationCallback(&notif_client);
notif_client.enumerator = nullptr;
}
hr = enumerator->RegisterEndpointNotificationCallback(&notif_client);
if (hr != S_OK) {
if (hr == S_OK) {
notif_client.enumerator = enumerator;
} else {
ERR_PRINT("WASAPI: RegisterEndpointNotificationCallback error");
}
@ -302,12 +329,13 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
audioProps.bIsOffload = FALSE;
audioProps.eCategory = AudioCategory_GameEffects;
hr = ((IAudioClient3 *)p_device->audio_client.Get())->SetClientProperties(&audioProps);
hr = ((IAudioClient3 *)p_device->audio_client)->SetClientProperties(&audioProps);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: SetClientProperties failed with error 0x" + String::num_uint64(hr, 16) + ".");
}
hr = p_device->audio_client->GetMixFormat(&pwfex);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
// From this point onward, CoTaskMemFree(pwfex) must be called before returning or pwfex will leak!
print_verbose("WASAPI: wFormatTag = " + itos(pwfex->wFormatTag));
print_verbose("WASAPI: nChannels = " + itos(pwfex->nChannels));
@ -331,6 +359,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
print_verbose("WASAPI: closest->cbSize = " + itos(closest->cbSize));
WARN_PRINT("WASAPI: Using closest match instead");
CoTaskMemFree(pwfex);
pwfex = closest;
}
}
@ -350,11 +379,13 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
p_device->format_tag = WAVE_FORMAT_IEEE_FLOAT;
} else {
ERR_PRINT("WASAPI: Format not supported");
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}
} else {
if (p_device->format_tag != WAVE_FORMAT_PCM && p_device->format_tag != WAVE_FORMAT_IEEE_FLOAT) {
ERR_PRINT("WASAPI: Format not supported");
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}
}
@ -367,10 +398,28 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
pwfex->nAvgBytesPerSec = pwfex->nSamplesPerSec * pwfex->nChannels * (pwfex->wBitsPerSample / 8);
}
hr = p_device->audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, streamflags, p_input ? REFTIMES_PER_SEC : 0, 0, pwfex, nullptr);
ERR_FAIL_COND_V_MSG(hr != S_OK, ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
if (p_reinit) {
// In case we're trying to re-initialize the device, prevent throwing this error on the console,
// otherwise if there is currently no device available this will spam the console.
if (hr != S_OK) {
print_verbose("WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
CoTaskMemFree(pwfex);
return ERR_CANT_OPEN;
}
} else {
if (unlikely(hr != S_OK)) {
CoTaskMemFree(pwfex);
ERR_FAIL_V_MSG(ERR_CANT_OPEN, "WASAPI: Initialize failed with error 0x" + String::num_uint64(hr, 16) + ".");
}
}
UINT32 max_frames;
hr = p_device->audio_client->GetBufferSize(&max_frames);
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
if (unlikely(hr != S_OK)) {
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}
// Due to WASAPI Shared Mode we have no control of the buffer size
if (!p_input) {
@ -385,7 +434,7 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
}
} else {
IAudioClient3 *device_audio_client_3 = (IAudioClient3 *)p_device->audio_client.Get();
IAudioClient3 *device_audio_client_3 = (IAudioClient3 *)p_device->audio_client;
// AUDCLNT_STREAMFLAGS_RATEADJUST is an invalid flag with IAudioClient3, therefore we have to use
// the closest supported mix rate supported by the audio driver.
@ -444,7 +493,10 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
} else {
hr = p_device->audio_client->GetService(IID_IAudioRenderClient, (void **)&p_device->render_client);
}
ERR_FAIL_COND_V(hr != S_OK, ERR_CANT_OPEN);
if (unlikely(hr != S_OK)) {
CoTaskMemFree(pwfex);
ERR_FAIL_V(ERR_CANT_OPEN);
}
// Free memory
CoTaskMemFree(pwfex);
@ -455,6 +507,11 @@ Error AudioDriverWASAPI::audio_device_init(AudioDeviceWASAPI *p_device, bool p_i
Error AudioDriverWASAPI::init_output_device(bool p_reinit) {
Error err = audio_device_init(&audio_output, false, p_reinit);
if (err != OK) {
// We've tried to init the device, but have failed. Time to clean up.
Error finish_err = finish_output_device();
if (finish_err != OK) {
ERR_PRINT("WASAPI: finish_output_device error after failed output audio_device_init");
}
return err;
}
@ -495,6 +552,11 @@ Error AudioDriverWASAPI::init_output_device(bool p_reinit) {
Error AudioDriverWASAPI::init_input_device(bool p_reinit) {
Error err = audio_device_init(&audio_input, true, p_reinit);
if (err != OK) {
// We've tried to init the device, but have failed. Time to clean up.
Error finish_err = finish_input_device();
if (finish_err != OK) {
ERR_PRINT("WASAPI: finish_input_device error after failed input audio_device_init");
}
return err;
}
@ -516,9 +578,9 @@ Error AudioDriverWASAPI::audio_device_finish(AudioDeviceWASAPI *p_device) {
p_device->active.clear();
}
p_device->audio_client.Reset();
p_device->render_client.Reset();
p_device->capture_client.Reset();
SAFE_RELEASE(p_device->audio_client)
SAFE_RELEASE(p_device->render_client)
SAFE_RELEASE(p_device->capture_client)
return OK;
}
@ -588,7 +650,7 @@ PackedStringArray AudioDriverWASAPI::audio_device_get_list(bool p_input) {
PROPVARIANT propvar;
PropVariantInit(&propvar);
hr = props->GetValue(PKEY_Device_FriendlyName, &propvar);
hr = props->GetValue(PKEY_Device_FriendlyNameGodot, &propvar);
ERR_BREAK(hr != S_OK);
list.push_back(String(propvar.pwszVal));
@ -817,9 +879,15 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
}
if (!ad->audio_output.audio_client) {
Error err = ad->init_output_device(true);
if (err == OK) {
ad->start();
if (output_reinit_countdown < 1) {
Error err = ad->init_output_device(true);
if (err == OK) {
ad->start();
} else {
output_reinit_countdown = 1000;
}
} else {
output_reinit_countdown--;
}
avail_frames = 0;
@ -890,9 +958,15 @@ void AudioDriverWASAPI::thread_func(void *p_udata) {
}
if (!ad->audio_input.audio_client) {
Error err = ad->init_input_device(true);
if (err == OK) {
ad->input_start();
if (input_reinit_countdown < 1) {
Error err = ad->init_input_device(true);
if (err == OK) {
ad->input_start();
} else {
input_reinit_countdown = 1000;
}
} else {
input_reinit_countdown--;
}
}
}

View file

@ -40,18 +40,15 @@
#include <audioclient.h>
#include <mmdeviceapi.h>
#include <wrl/client.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
using Microsoft::WRL::ComPtr;
class AudioDriverWASAPI : public AudioDriver {
class AudioDeviceWASAPI {
public:
ComPtr<IAudioClient> audio_client = nullptr;
ComPtr<IAudioRenderClient> render_client = nullptr; // Output
ComPtr<IAudioCaptureClient> capture_client = nullptr; // Input
IAudioClient *audio_client = nullptr;
IAudioRenderClient *render_client = nullptr; // Output
IAudioCaptureClient *capture_client = nullptr; // Input
SafeFlag active;
WORD format_tag = 0;