mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1103824 - Ensure first initialization of IAudioClient happens on STA thread. r=padenot
This commit is contained in:
parent
4e2c55e078
commit
0bbda78298
@ -131,6 +131,15 @@ void InitLibrary()
|
|||||||
Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
|
Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
|
||||||
PrefChanged(PREF_CUBEB_LATENCY, nullptr);
|
PrefChanged(PREF_CUBEB_LATENCY, nullptr);
|
||||||
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
|
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
// Ensure the first call to cubeb_init is made from the main thread.
|
||||||
|
MOZ_ASSERT(NS_IsMainThread() && !sCubebContext);
|
||||||
|
cubeb * context;
|
||||||
|
if (cubeb_init(&context, "FirstInitContext") == CUBEB_OK) {
|
||||||
|
cubeb_destroy(context);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownLibrary()
|
void ShutdownLibrary()
|
||||||
|
@ -144,28 +144,17 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct auto_com {
|
struct auto_com {
|
||||||
auto_com() {
|
auto_com(DWORD dwCoInit = COINIT_MULTITHREADED) {
|
||||||
result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
result = CoInitializeEx(NULL, dwCoInit);
|
||||||
}
|
}
|
||||||
~auto_com() {
|
~auto_com() {
|
||||||
if (result == RPC_E_CHANGED_MODE) {
|
if (ok()) {
|
||||||
// This is not an error, COM was not initialized by this function, so it is
|
|
||||||
// not necessary to uninit it.
|
|
||||||
LOG("COM already initialized in STA.\n");
|
|
||||||
} else if (result == S_FALSE) {
|
|
||||||
// This is not an error. We are allowed to call CoInitializeEx more than
|
|
||||||
// once, as long as it is matches by an CoUninitialize call.
|
|
||||||
// We do that in the dtor which is guaranteed to be called.
|
|
||||||
LOG("COM already initialized in MTA\n");
|
|
||||||
}
|
|
||||||
if (SUCCEEDED(result)) {
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool ok() {
|
bool ok() {
|
||||||
return result == RPC_E_CHANGED_MODE || SUCCEEDED(result);
|
return SUCCEEDED(result);
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -492,6 +481,7 @@ wasapi_stream_render_loop(LPVOID stream)
|
|||||||
auto_com com;
|
auto_com com;
|
||||||
if (!com.ok()) {
|
if (!com.ok()) {
|
||||||
LOG("COM initialization failed on render_loop thread.\n");
|
LOG("COM initialization failed on render_loop thread.\n");
|
||||||
|
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,14 +678,19 @@ HRESULT get_default_endpoint(IMMDevice ** device)
|
|||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
owned_critical_section g_first_init_lock;
|
||||||
|
bool g_first_init = false;
|
||||||
} // namespace anonymous
|
} // namespace anonymous
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
int wasapi_init(cubeb ** context, char const * context_name)
|
int wasapi_init(cubeb ** context, char const * context_name)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
auto_lock lock(&g_first_init_lock);
|
||||||
auto_com com;
|
if (!g_first_init) {
|
||||||
if (!com.ok()) {
|
// Per the MSDN documentation for IAudioClient, the first use *must* be made from an STA thread.
|
||||||
|
auto_com com(COINIT_APARTMENTTHREADED);
|
||||||
|
if (FAILED(com.result)) {
|
||||||
return CUBEB_ERROR;
|
return CUBEB_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,12 +698,37 @@ int wasapi_init(cubeb ** context, char const * context_name)
|
|||||||
so that this backend is not incorrectly enabled on platforms that don't
|
so that this backend is not incorrectly enabled on platforms that don't
|
||||||
support WASAPI. */
|
support WASAPI. */
|
||||||
IMMDevice * device;
|
IMMDevice * device;
|
||||||
hr = get_default_endpoint(&device);
|
HRESULT hr = get_default_endpoint(&device);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
LOG("Could not get device.\n");
|
LOG("Could not get device: %x\n", hr);
|
||||||
return CUBEB_ERROR;
|
return CUBEB_ERROR;
|
||||||
}
|
}
|
||||||
|
IAudioClient * client;
|
||||||
|
hr = device->Activate(__uuidof(IAudioClient),
|
||||||
|
CLSCTX_INPROC_SERVER,
|
||||||
|
NULL, (void **)&client);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
WAVEFORMATEX * mix_format;
|
||||||
|
hr = client->GetMixFormat(&mix_format);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
hr = client->Initialize(AUDCLNT_SHAREMODE_SHARED,
|
||||||
|
AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
|
||||||
|
AUDCLNT_STREAMFLAGS_NOPERSIST,
|
||||||
|
ms_to_hns(100),
|
||||||
|
0,
|
||||||
|
mix_format,
|
||||||
|
NULL);
|
||||||
|
CoTaskMemFree(mix_format);
|
||||||
|
g_first_init = true;
|
||||||
|
}
|
||||||
|
SafeRelease(client);
|
||||||
|
}
|
||||||
SafeRelease(device);
|
SafeRelease(device);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
LOG("Could not initialize IAudioClient: %x\n", hr);
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb));
|
cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb));
|
||||||
|
|
||||||
@ -784,10 +804,8 @@ wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
|
|||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IAudioClient * client;
|
IAudioClient * client;
|
||||||
WAVEFORMATEX * mix_format;
|
WAVEFORMATEX * mix_format;
|
||||||
auto_com com;
|
XASSERT(g_first_init);
|
||||||
if (!com.ok()) {
|
auto_com com; /* don't care what COM mode we're in here */
|
||||||
return CUBEB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
XASSERT(ctx && max_channels);
|
XASSERT(ctx && max_channels);
|
||||||
|
|
||||||
@ -825,10 +843,8 @@ wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * laten
|
|||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IAudioClient * client;
|
IAudioClient * client;
|
||||||
REFERENCE_TIME default_period;
|
REFERENCE_TIME default_period;
|
||||||
auto_com com;
|
XASSERT(g_first_init);
|
||||||
if (!com.ok()) {
|
auto_com com; /* don't care what COM mode we're in here */
|
||||||
return CUBEB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMMDevice * device;
|
IMMDevice * device;
|
||||||
hr = get_default_endpoint(&device);
|
hr = get_default_endpoint(&device);
|
||||||
@ -872,10 +888,8 @@ wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
|||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
IAudioClient * client;
|
IAudioClient * client;
|
||||||
WAVEFORMATEX * mix_format;
|
WAVEFORMATEX * mix_format;
|
||||||
auto_com com;
|
XASSERT(g_first_init);
|
||||||
if (!com.ok()) {
|
auto_com com; /* don't care what COM mode we're in here */
|
||||||
return CUBEB_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMMDevice * device;
|
IMMDevice * device;
|
||||||
hr = get_default_endpoint(&device);
|
hr = get_default_endpoint(&device);
|
||||||
|
Loading…
Reference in New Issue
Block a user