From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/recognizer.c | 54 +++++++++++++++++++++--- dlls/windows.media.speech/tests/speech.c | 4 +- 2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/dlls/windows.media.speech/recognizer.c b/dlls/windows.media.speech/recognizer.c index 7a84647211a..2fdd0fc7625 100644 --- a/dlls/windows.media.speech/recognizer.c +++ b/dlls/windows.media.speech/recognizer.c @@ -162,7 +162,8 @@ struct session struct list result_handlers;
HANDLE worker_thread; - BOOLEAN worker_running; + HANDLE worker_paused_event, worker_resume_event; + BOOLEAN worker_running, worker_paused; CRITICAL_SECTION cs; };
@@ -181,7 +182,7 @@ static DWORD CALLBACK session_worker_thread_cb( void *args ) { ISpeechContinuousRecognitionSession *iface = args; struct session *impl = impl_from_ISpeechContinuousRecognitionSession(iface); - BOOLEAN running = FALSE; + BOOLEAN running = FALSE, paused = FALSE;
EnterCriticalSection(&impl->cs); running = impl->worker_running; @@ -191,10 +192,18 @@ static DWORD CALLBACK session_worker_thread_cb( void *args ) { EnterCriticalSection(&impl->cs); running = impl->worker_running; + paused = impl->worker_paused; LeaveCriticalSection(&impl->cs);
/* TODO: Send mic data to recognizer and handle results. */
+ if (paused) + { + TRACE("Recognition session paused!\n"); + SetEvent(impl->worker_paused_event); + WaitForSingleObject(impl->worker_resume_event, INFINITE); + } + Sleep(500); /* Sleep to slow down spinning for now. */ }
@@ -241,6 +250,8 @@ static HRESULT session_destroy_worker_thread( ISpeechContinuousRecognitionSessio EnterCriticalSection(&impl->cs); if (impl->worker_thread) { + SetEvent(impl->worker_resume_event); /* Unblock the worker in case it was paused. */ + if (WaitForSingleObject(impl->worker_thread, 1000)) ERR("Wait for shut down recognition session timed out!\n");
@@ -381,19 +392,44 @@ static HRESULT WINAPI session_CancelAsync( ISpeechContinuousRecognitionSession *
static HRESULT session_pause_async( IInspectable *invoker ) { + struct session *impl = impl_from_ISpeechContinuousRecognitionSession((ISpeechContinuousRecognitionSession *)invoker); + + EnterCriticalSection(&impl->cs); + if (impl->worker_thread && impl->worker_running && !impl->worker_paused) + { + impl->worker_paused = TRUE; + LeaveCriticalSection(&impl->cs); + + WaitForSingleObject(impl->worker_paused_event, INFINITE); + } + else LeaveCriticalSection(&impl->cs); + return S_OK; }
static HRESULT WINAPI session_PauseAsync( ISpeechContinuousRecognitionSession *iface, IAsyncAction **action ) { - FIXME("iface %p, action %p stub!\n", iface, action); - return async_action_create(NULL, session_pause_async, action); + TRACE("iface %p, action %p stub!\n", iface, action); + return async_action_create((IInspectable *)iface, session_pause_async, action); }
static HRESULT WINAPI session_Resume( ISpeechContinuousRecognitionSession *iface ) { - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; + struct session *impl = impl_from_ISpeechContinuousRecognitionSession(iface); + + TRACE("iface %p stub!\n", iface); + + EnterCriticalSection(&impl->cs); + if (impl->worker_thread && impl->worker_running && impl->worker_paused) + { + impl->worker_paused = FALSE; + LeaveCriticalSection(&impl->cs); + + SetEvent(impl->worker_resume_event); + } + else LeaveCriticalSection(&impl->cs); + + return S_OK; }
static HRESULT WINAPI session_add_Completed( ISpeechContinuousRecognitionSession *iface, @@ -910,6 +946,10 @@ static HRESULT WINAPI recognizer_factory_Create( ISpeechRecognizerFactory *iface /* Init ISpeechContinuousRecognitionSession */ session->ISpeechContinuousRecognitionSession_iface.lpVtbl = &session_vtbl; session->ref = 1; + session->worker_paused_event = CreateEventW(NULL, FALSE, FALSE, NULL); + session->worker_resume_event = CreateEventW(NULL, FALSE, FALSE, NULL); + if (FAILED(hr = HRESULT_FROM_WIN32(GetLastError())) || !session->worker_resume_event || !session->worker_resume_event) + goto error;
list_init(&session->completed_handlers); list_init(&session->result_handlers); @@ -934,6 +974,8 @@ static HRESULT WINAPI recognizer_factory_Create( ISpeechRecognizerFactory *iface
error: if (session->constraints) IVector_ISpeechRecognitionConstraint_Release(session->constraints); + CloseHandle(session->worker_paused_event); + CloseHandle(session->worker_resume_event); DeleteCriticalSection(&session->cs); free(session); free(impl); diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 8b31031d3c5..196d0a98302 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -1798,11 +1798,11 @@ static void test_Recognition(void) IAsyncAction_Release(action2);
hr = ISpeechContinuousRecognitionSession_Resume(session); - todo_wine ok(hr == S_OK, "ISpeechContinuousRecognitionSession_Resume failed, hr %#lx.\n", hr); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_Resume failed, hr %#lx.\n", hr);
/* Resume when already resumed. */ hr = ISpeechContinuousRecognitionSession_Resume(session); - todo_wine ok(hr == S_OK, "ISpeechContinuousRecognitionSession_Resume failed, hr %#lx.\n", hr); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_Resume failed, hr %#lx.\n", hr);
recog_state = 0xdeadbeef; hr = ISpeechRecognizer2_get_State(recognizer2, &recog_state);