diff --git a/plugins/win-wasapi/win-wasapi.cpp b/plugins/win-wasapi/win-wasapi.cpp index 08aeca496..2dcc858f7 100644 --- a/plugins/win-wasapi/win-wasapi.cpp +++ b/plugins/win-wasapi/win-wasapi.cpp @@ -182,7 +182,7 @@ class WASAPISource { std::atomic isDefaultDevice = false; bool previouslyFailed = false; - WinHandle reconnectThread; + WinHandle reconnectThread = NULL; class CallbackStartCapture : public ARtwqAsyncCallback { public: @@ -238,6 +238,7 @@ class WASAPISource { WinHandle stopSignal; WinHandle receiveSignal; WinHandle restartSignal; + WinHandle reconnectExitSignal; WinHandle exitSignal; WinHandle initSignal; DWORD reconnectDuration = 0; @@ -298,6 +299,9 @@ public: void Update(obs_data_t *settings); void OnWindowChanged(obs_data_t *settings); + void Activate(); + void Deactivate(); + void SetDefaultDevice(EDataFlow flow, ERole role, LPCWSTR id); void OnStartCapture(); @@ -390,6 +394,10 @@ WASAPISource::WASAPISource(obs_data_t *settings, obs_source_t *source_, if (!restartSignal.Valid()) throw "Could not create restart signal"; + reconnectExitSignal = CreateEvent(nullptr, true, false, nullptr); + if (!reconnectExitSignal.Valid()) + throw "Could not create reconnect exit signal"; + exitSignal = CreateEvent(nullptr, true, false, nullptr); if (!exitSignal.Valid()) throw "Could not create exit signal"; @@ -402,11 +410,6 @@ WASAPISource::WASAPISource(obs_data_t *settings, obs_source_t *source_, if (!reconnectSignal.Valid()) throw "Could not create reconnect signal"; - reconnectThread = CreateThread( - nullptr, 0, WASAPISource::ReconnectThread, this, 0, nullptr); - if (!reconnectThread.Valid()) - throw "Failed to create reconnect thread"; - notify = new WASAPINotify(this); if (!notify) throw "Could not create WASAPINotify"; @@ -525,6 +528,9 @@ void WASAPISource::Start() void WASAPISource::Stop() { + if (!reconnectThread.Valid()) + WaitForSingleObject(reconnectSignal, INFINITE); + SetEvent(stopSignal); blog(LOG_INFO, "WASAPI: Device '%s' Terminated", device_name.c_str()); @@ -532,11 +538,15 @@ void WASAPISource::Stop() if (rtwq_supported) SetEvent(receiveSignal); - WaitForSingleObject(idleSignal, INFINITE); + if (reconnectThread.Valid()) + WaitForSingleObject(idleSignal, INFINITE); SetEvent(exitSignal); - WaitForSingleObject(reconnectThread, INFINITE); + if (reconnectThread.Valid()) { + SetEvent(reconnectExitSignal); + WaitForSingleObject(reconnectThread, INFINITE); + } if (rtwq_supported) rtwq_unlock_work_queue(sampleReady.GetQueueId()); @@ -657,6 +667,25 @@ void WASAPISource::OnWindowChanged(obs_data_t *settings) SetEvent(restartSignal); } +void WASAPISource::Activate() +{ + if (!reconnectThread.Valid()) { + ResetEvent(reconnectExitSignal); + reconnectThread = CreateThread(nullptr, 0, + WASAPISource::ReconnectThread, + this, 0, nullptr); + } +} + +void WASAPISource::Deactivate() +{ + if (reconnectThread.Valid()) { + SetEvent(reconnectExitSignal); + WaitForSingleObject(reconnectThread, INFINITE); + reconnectThread = NULL; + } +} + ComPtr WASAPISource::InitDevice(IMMDeviceEnumerator *enumerator, bool isDefaultDevice, SourceType type, @@ -1005,10 +1034,15 @@ DWORD WINAPI WASAPISource::ReconnectThread(LPVOID param) WASAPISource *source = (WASAPISource *)param; const HANDLE sigs[] = { - source->exitSignal, + source->reconnectExitSignal, source->reconnectSignal, }; + const HANDLE reconnect_sigs[] = { + source->reconnectExitSignal, + source->stopSignal, + }; + bool exit = false; while (!exit) { const DWORD ret = WaitForMultipleObjects(_countof(sigs), sigs, @@ -1020,8 +1054,10 @@ DWORD WINAPI WASAPISource::ReconnectThread(LPVOID param) default: assert(ret == (WAIT_OBJECT_0 + 1)); if (source->reconnectDuration > 0) { - WaitForSingleObject(source->stopSignal, - source->reconnectDuration); + WaitForMultipleObjects( + _countof(reconnect_sigs), + reconnect_sigs, false, + source->reconnectDuration); } source->Start(); } @@ -1426,6 +1462,16 @@ static void UpdateWASAPISource(void *obj, obs_data_t *settings) static_cast(obj)->Update(settings); } +static void ActivateWASAPISource(void *obj) +{ + static_cast(obj)->Activate(); +} + +static void DeactivateWASAPISource(void *obj) +{ + static_cast(obj)->Deactivate(); +} + static bool UpdateWASAPIMethod(obs_properties_t *props, obs_property_t *, obs_data_t *settings) { @@ -1542,6 +1588,8 @@ void RegisterWASAPIInput() info.create = CreateWASAPIInput; info.destroy = DestroyWASAPISource; info.update = UpdateWASAPISource; + info.activate = ActivateWASAPISource; + info.deactivate = DeactivateWASAPISource; info.get_defaults = GetWASAPIDefaultsInput; info.get_properties = GetWASAPIPropertiesInput; info.icon_type = OBS_ICON_TYPE_AUDIO_INPUT; @@ -1559,6 +1607,8 @@ void RegisterWASAPIDeviceOutput() info.create = CreateWASAPIDeviceOutput; info.destroy = DestroyWASAPISource; info.update = UpdateWASAPISource; + info.activate = ActivateWASAPISource; + info.deactivate = DeactivateWASAPISource; info.get_defaults = GetWASAPIDefaultsDeviceOutput; info.get_properties = GetWASAPIPropertiesDeviceOutput; info.icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT; @@ -1576,6 +1626,8 @@ void RegisterWASAPIProcessOutput() info.create = CreateWASAPIProcessOutput; info.destroy = DestroyWASAPISource; info.update = UpdateWASAPISource; + info.activate = ActivateWASAPISource; + info.deactivate = DeactivateWASAPISource; info.get_defaults = GetWASAPIDefaultsProcessOutput; info.get_properties = GetWASAPIPropertiesProcessOutput; info.icon_type = OBS_ICON_TYPE_PROCESS_AUDIO_OUTPUT;