diff --git a/dlls/windows.media.speech/recognizer.c b/dlls/windows.media.speech/recognizer.c index 7f4c7429929..da219d6bd0a 100644 --- a/dlls/windows.media.speech/recognizer.c +++ b/dlls/windows.media.speech/recognizer.c @@ -34,6 +34,7 @@ struct session ISpeechContinuousRecognitionSession ISpeechContinuousRecognitionSession_iface; LONG ref; + struct list completed_handlers; struct list result_handlers; }; @@ -83,6 +84,7 @@ static ULONG WINAPI session_Release( ISpeechContinuousRecognitionSession *iface if (!ref) { + typed_event_handlers_clear(&impl->completed_handlers); typed_event_handlers_clear(&impl->result_handlers); free(impl); } @@ -162,14 +164,17 @@ static HRESULT WINAPI session_add_Completed( ISpeechContinuousRecognitionSession ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs *handler, EventRegistrationToken *token ) { - FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); - return E_NOTIMPL; + struct session *impl = impl_from_ISpeechContinuousRecognitionSession(iface); + TRACE("iface %p, handler %p, token %p.\n", iface, handler, token); + if (!handler) return E_INVALIDARG; + return typed_event_handlers_append(&impl->completed_handlers, (ITypedEventHandler_IInspectable_IInspectable *)handler, token); } static HRESULT WINAPI session_remove_Completed( ISpeechContinuousRecognitionSession *iface, EventRegistrationToken token ) { - FIXME("iface %p, token.value %#I64x stub!\n", iface, token.value); - return E_NOTIMPL; + struct session *impl = impl_from_ISpeechContinuousRecognitionSession(iface); + TRACE("iface %p, token.value %#I64x.\n", iface, token.value); + return typed_event_handlers_remove(&impl->completed_handlers, &token); } static HRESULT WINAPI session_add_ResultGenerated( ISpeechContinuousRecognitionSession *iface, @@ -645,6 +650,7 @@ static HRESULT WINAPI recognizer_factory_Create( ISpeechRecognizerFactory *iface session->ISpeechContinuousRecognitionSession_iface.lpVtbl = &session_vtbl; session->ref = 1; + list_init(&session->completed_handlers); list_init(&session->result_handlers); impl->ISpeechRecognizer_iface.lpVtbl = &speech_recognizer_vtbl; diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 80e5d9af634..fc0a8d762c1 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -46,6 +46,12 @@ #define impl_from_IHandler_RecognitionResult impl_from_ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionResultGeneratedEventArgs #define IHandler_RecognitionResult_iface ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionResultGeneratedEventArgs_iface +#define IHandler_RecognitionCompleted ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs +#define IHandler_RecognitionCompletedVtbl ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgsVtbl +#define IID_IHandler_RecognitionCompleted IID_ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs +#define impl_from_IHandler_RecognitionCompleted impl_from_ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs +#define IHandler_RecognitionCompleted_iface ITypedEventHandler_SpeechContinuousRecognitionSession_SpeechContinuousRecognitionCompletedEventArgs_iface + HRESULT WINAPI (*pDllGetActivationFactory)(HSTRING, IActivationFactory **); static BOOL is_win10_1507 = FALSE; @@ -86,6 +92,72 @@ static const char *debugstr_hstring(HSTRING hstr) return wine_dbgstr_wn(str, len); } +struct completed_event_handler +{ + IHandler_RecognitionCompleted IHandler_RecognitionCompleted_iface; + LONG ref; +}; + +static inline struct completed_event_handler *impl_from_IHandler_RecognitionCompleted( IHandler_RecognitionCompleted *iface ) +{ + return CONTAINING_RECORD(iface, struct completed_event_handler, IHandler_RecognitionCompleted_iface); +} + +HRESULT WINAPI completed_event_handler_QueryInterface( IHandler_RecognitionCompleted *iface, REFIID iid, void **out ) +{ + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IHandler_RecognitionCompleted)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + trace("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +ULONG WINAPI completed_event_handler_AddRef( IHandler_RecognitionCompleted *iface ) +{ + struct completed_event_handler *impl = impl_from_IHandler_RecognitionCompleted(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + return ref; +} + +ULONG WINAPI completed_event_handler_Release( IHandler_RecognitionCompleted *iface ) +{ + struct completed_event_handler *impl = impl_from_IHandler_RecognitionCompleted(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + return ref; +} + +HRESULT WINAPI completed_event_handler_Invoke( IHandler_RecognitionCompleted *iface, + ISpeechContinuousRecognitionSession *sender, + ISpeechContinuousRecognitionCompletedEventArgs *args ) +{ + trace("iface %p, sender %p, args %p.\n", iface, sender, args); + return S_OK; +} + +static const struct IHandler_RecognitionCompletedVtbl completed_event_handler_vtbl = +{ + /* IUnknown methods */ + completed_event_handler_QueryInterface, + completed_event_handler_AddRef, + completed_event_handler_Release, + /* ITypedEventHandler methods */ + completed_event_handler_Invoke +}; + +static HRESULT WINAPI completed_event_handler_create_static( struct completed_event_handler *impl ) +{ + impl->IHandler_RecognitionCompleted_iface.lpVtbl = &completed_event_handler_vtbl; + impl->ref = 1; + + return S_OK; +} + struct recognition_result_handler { IHandler_RecognitionResult IHandler_RecognitionResult_iface; @@ -651,6 +723,7 @@ static void test_SpeechRecognizer(void) IInspectable *inspectable = NULL; IClosable *closable = NULL; ILanguage *language = NULL; + struct completed_event_handler completed_handler; struct recognition_result_handler result_handler; EventRegistrationToken token = { .value = 0 }; HSTRING hstr, hstr_lang; @@ -728,6 +801,18 @@ static void test_SpeechRecognizer(void) check_refcount(session, 2); check_refcount(inspectable, 3); + hr = ISpeechContinuousRecognitionSession_add_Completed(session, NULL, &token); + ok(hr == E_INVALIDARG, "ISpeechContinuousRecognitionSession_add_ResultGenerated failed, hr %#lx.\n", hr); + + token.value = 0xdeadbeef; + completed_event_handler_create_static(&completed_handler); + hr = ISpeechContinuousRecognitionSession_add_Completed(session, &completed_handler.IHandler_RecognitionCompleted_iface, &token); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_add_ResultGenerated failed, hr %#lx.\n", hr); + ok(token.value != 0xdeadbeef, "Got unexpexted token: %#I64x.\n", token.value); + + hr = ISpeechContinuousRecognitionSession_remove_Completed(session, token); + ok(hr == S_OK, "ISpeechContinuousRecognitionSession_remove_ResultGenerated failed, hr %#lx.\n", hr); + hr = ISpeechContinuousRecognitionSession_add_ResultGenerated(session, NULL, &token); ok(hr == E_INVALIDARG, "ISpeechContinuousRecognitionSession_add_ResultGenerated failed, hr %#lx.\n", hr);