From ab7d370ada0e71b4b24ee440f169b9bd209740ca Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sat, 2 Oct 2021 21:23:09 -0700 Subject: [PATCH] win-wasapi Improve default device handling Remove lastNotifyTime throttle. Could ignore last device notification. Will bring back if necessary, but seemed like overkill. Make isInputDevice const for safety. Make isDefaultDevice atomic. Allows it to be accessed simultaneously from settings and notification callback threads. Race between setting change in OBS and Windows is not a problem, a signal will be sent after both to consolidate. Worst that should happen is a redundant reconnect cycle. Only read/write default_id from notification callback for thread safety. --- plugins/win-wasapi/win-wasapi.cpp | 44 ++++++++++++------------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/plugins/win-wasapi/win-wasapi.cpp b/plugins/win-wasapi/win-wasapi.cpp index 757d9f2c5..d5f8d6d04 100644 --- a/plugins/win-wasapi/win-wasapi.cpp +++ b/plugins/win-wasapi/win-wasapi.cpp @@ -102,10 +102,9 @@ class WASAPISource { PFN_RtwqPutWorkItem rtwq_put_work_item = NULL; PFN_RtwqPutWaitingWorkItem rtwq_put_waiting_work_item = NULL; bool rtwq_supported = false; - uint64_t lastNotifyTime = 0; - bool isInputDevice; + const bool isInputDevice; std::atomic useDeviceTiming = false; - bool isDefaultDevice = false; + std::atomic isDefaultDevice = false; bool previouslyFailed = false; WinHandle reconnectThread; @@ -184,8 +183,7 @@ class WASAPISource { static ComPtr InitDevice(IMMDeviceEnumerator *enumerator, bool isDefaultDevice, bool isInputDevice, - const string device_id, - wstring &default_id); + const string device_id); static ComPtr InitClient(IMMDevice *device, bool isInputDevice, enum speaker_layout &speakers, @@ -454,8 +452,7 @@ void WASAPISource::Update(obs_data_t *settings) ComPtr WASAPISource::InitDevice(IMMDeviceEnumerator *enumerator, bool isDefaultDevice, bool isInputDevice, - const string device_id, - wstring &default_id) + const string device_id) { ComPtr device; @@ -466,12 +463,6 @@ ComPtr WASAPISource::InitDevice(IMMDeviceEnumerator *enumerator, device.Assign()); if (FAILED(res)) throw HRError("Failed GetDefaultAudioEndpoint", res); - - CoTaskMemPtr id; - res = device->GetId(&id); - if (FAILED(res)) - throw HRError("Failed to get default id", res); - default_id = id; } else { wchar_t *w_id; os_utf8_to_wcs_ptr(device_id.c_str(), device_id.size(), &w_id); @@ -624,8 +615,7 @@ ComPtr WASAPISource::InitCapture(IAudioClient *client, void WASAPISource::Initialize() { ComPtr device = InitDevice(enumerator, isDefaultDevice, - isInputDevice, device_id, - default_id); + isInputDevice, device_id); device_name = GetDeviceName(device); @@ -918,24 +908,24 @@ void WASAPISource::SetDefaultDevice(EDataFlow flow, ERole role, LPCWSTR id) if (!isDefaultDevice) return; - EDataFlow expectedFlow = isInputDevice ? eCapture : eRender; - ERole expectedRole = isInputDevice ? eCommunications : eConsole; - + const EDataFlow expectedFlow = isInputDevice ? eCapture : eRender; + const ERole expectedRole = isInputDevice ? eCommunications : eConsole; if (flow != expectedFlow || role != expectedRole) return; - if (id && default_id.compare(id) == 0) - return; + + if (id) { + if (default_id.compare(id) == 0) + return; + default_id = id; + } else { + if (default_id.empty()) + return; + default_id.clear(); + } blog(LOG_INFO, "WASAPI: Default %s device changed", isInputDevice ? "input" : "output"); - /* reset device only once every 300ms */ - uint64_t t = os_gettime_ns(); - if (t - lastNotifyTime < 300000000) - return; - - lastNotifyTime = t; - SetEvent(restartSignal); }