|
@@ -182,7 +182,7 @@ class WASAPISource {
|
|
|
std::atomic<bool> 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<IMMDevice> 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<WASAPISource *>(obj)->Update(settings);
|
|
|
}
|
|
|
|
|
|
+static void ActivateWASAPISource(void *obj)
|
|
|
+{
|
|
|
+ static_cast<WASAPISource *>(obj)->Activate();
|
|
|
+}
|
|
|
+
|
|
|
+static void DeactivateWASAPISource(void *obj)
|
|
|
+{
|
|
|
+ static_cast<WASAPISource *>(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;
|