PA_THREAD_ID dwThreadId;\r
HANDLE hThread;\r
HANDLE hCloseRequest;\r
- HANDLE hThreadDone;\r
+ HANDLE hThreadStart; //!< signalled by thread on start\r
+ HANDLE hThreadExit; //!< signalled by thread on exit\r
HANDLE hBlockingOpStreamRD;\r
HANDLE hBlockingOpStreamWR;\r
\r
if (answer != paFormatIsSupported)\r
{\r
// If mono, then driver does not support 1 channel, we use internal workaround\r
- // of tiny software mixing functionality, e.g. we provide to user buffer for 1 channel\r
- // but then mix into 2 of device buffer\r
+ // of tiny software mixing functionality, e.g. we provide to user buffer 1 channel\r
+ // but then mix into 2 for device buffer\r
if (params->channelCount == 1)\r
{\r
WAVEFORMATEXTENSIBLE stereo = { 0 };\r
SAFE_RELEASE(stream->outVol);\r
\r
SAFE_CLOSE(stream->hThread);\r
- SAFE_CLOSE(stream->hThreadDone);\r
+ SAFE_CLOSE(stream->hThreadStart);\r
+ SAFE_CLOSE(stream->hThreadExit);\r
SAFE_CLOSE(stream->hCloseRequest);\r
SAFE_CLOSE(stream->hBlockingOpStreamRD);\r
SAFE_CLOSE(stream->hBlockingOpStreamWR);\r
// Create thread\r
if (!stream->bBlocking)\r
{\r
- // Create thread done event\r
- stream->hThreadDone = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+ // Create thread events\r
+ stream->hThreadStart = CreateEvent(NULL, TRUE, FALSE, NULL);\r
+ stream->hThreadExit = CreateEvent(NULL, TRUE, FALSE, NULL);\r
\r
if ((stream->in.client && stream->in.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) ||\r
(stream->out.client && stream->out.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK))\r
if ((stream->hThread = CREATE_THREAD(ProcThreadPoll)) == NULL)\r
return paUnanticipatedHostError;\r
}\r
+\r
+ // Wait for thread to start\r
+ if (WaitForSingleObject(stream->hThreadStart, 60*1000) == WAIT_TIMEOUT)\r
+ return paUnanticipatedHostError;\r
}\r
else\r
{\r
// Issue command to thread to stop processing and wait for thread exit\r
if (!stream->bBlocking)\r
{\r
- SignalObjectAndWait(stream->hCloseRequest, stream->hThreadDone, INFINITE, FALSE);\r
+ SignalObjectAndWait(stream->hCloseRequest, stream->hThreadExit, INFINITE, FALSE);\r
}\r
else\r
// Blocking mode does not own thread\r
\r
// Close thread handles to allow restart\r
SAFE_CLOSE(stream->hThread);\r
- SAFE_CLOSE(stream->hThreadDone);\r
+ SAFE_CLOSE(stream->hThreadStart);\r
+ SAFE_CLOSE(stream->hThreadExit);\r
SAFE_CLOSE(stream->hCloseRequest);\r
SAFE_CLOSE(stream->hBlockingOpStreamRD);\r
SAFE_CLOSE(stream->hBlockingOpStreamWR);\r
if (!event[S_INPUT] || !event[S_OUTPUT])\r
{\r
PRINT(("WASAPI Thread: failed creating one or two event handles\n"));\r
+\r
+ // Prevent deadlocking in Pa_StreamStart\r
+ SetEvent(stream->hThreadStart);\r
+ // Exit\r
goto thread_end;\r
}\r
\r
// Signal: stream running\r
stream->running = TRUE;\r
\r
+ // Notify: thread started\r
+ SetEvent(stream->hThreadStart);\r
+\r
// Processing Loop\r
for (;;)\r
{\r
CloseHandle(event[S_INPUT]);\r
CloseHandle(event[S_OUTPUT]);\r
\r
- // Notify thread is exiting\r
- SetEvent(stream->hThreadDone);\r
+ // Notify: thread exited\r
+ SetEvent(stream->hThreadExit);\r
+\r
+ // Notify: not running\r
+ stream->running = FALSE;\r
\r
return 0;\r
}\r
// Signal: stream running\r
stream->running = TRUE;\r
\r
+ // Notify: thread started\r
+ SetEvent(stream->hThreadStart);\r
+\r
// Processing Loop\r
while (WaitForSingleObject(stream->hCloseRequest, sleep_ms) == WAIT_TIMEOUT)\r
{\r
// Process stop\r
_OnStreamStop(stream);\r
\r
- // Notify thread is exiting\r
- SetEvent(stream->hThreadDone);\r
+ // Notify: thread exited\r
+ SetEvent(stream->hThreadExit);\r
+\r
+ // Notify: not running\r
+ stream->running = FALSE;\r
\r
return 0;\r
}\r