Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/private.h | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index b1df726413d..2694b23beab 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -46,4 +46,46 @@
extern IActivationFactory *synthesizer_factory;
+ + +#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ + { \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ + } \ + static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ + } \ + static ULONG WINAPI pfx##_Release( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ + } \ + static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ + } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface ) +#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface ) + #endif
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/Makefile.in | 1 + dlls/windows.media.speech/classes.idl | 1 + dlls/windows.media.speech/main.c | 2 + dlls/windows.media.speech/private.h | 10 + dlls/windows.media.speech/recognizer.c | 253 +++++++++++++++++++++++ dlls/windows.media.speech/tests/speech.c | 2 +- 6 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 dlls/windows.media.speech/recognizer.c
diff --git a/dlls/windows.media.speech/Makefile.in b/dlls/windows.media.speech/Makefile.in index 74eb7b93fea..079578fb37f 100644 --- a/dlls/windows.media.speech/Makefile.in +++ b/dlls/windows.media.speech/Makefile.in @@ -3,6 +3,7 @@ IMPORTS = combase uuid
C_SRCS = \ main.c \ + recognizer.c \ synthesizer.c
IDL_SRCS = classes.idl diff --git a/dlls/windows.media.speech/classes.idl b/dlls/windows.media.speech/classes.idl index 6c141bf4768..4dd43cf6eed 100644 --- a/dlls/windows.media.speech/classes.idl +++ b/dlls/windows.media.speech/classes.idl @@ -16,4 +16,5 @@
#pragma makedep register
+#include "windows.media.speechrecognition.idl" #include "windows.media.speechsynthesis.idl" diff --git a/dlls/windows.media.speech/main.c b/dlls/windows.media.speech/main.c index 60aa1b1ab9e..295af6ea135 100644 --- a/dlls/windows.media.speech/main.c +++ b/dlls/windows.media.speech/main.c @@ -38,6 +38,8 @@ HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **fac
*factory = NULL;
+ if (!wcscmp(buffer, L"Windows.Media.SpeechRecognition.SpeechRecognizer")) + IActivationFactory_AddRef((*factory = recognizer_factory)); if (!wcscmp(buffer, L"Windows.Media.SpeechSynthesis.SpeechSynthesizer")) IActivationFactory_AddRef((*factory = synthesizer_factory));
diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index 2694b23beab..ece2a0934f2 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -37,6 +37,16 @@ #include "windows.globalization.h" #define WIDL_using_Windows_Media_SpeechSynthesis #include "windows.media.speechsynthesis.h" +#define WIDL_using_Windows_Media_SpeechRecognition +#include "windows.media.speechrecognition.h" + +/* + * + * Windows.Media.SpeechRecognition + * + */ + +extern IActivationFactory *recognizer_factory;
/* * diff --git a/dlls/windows.media.speech/recognizer.c b/dlls/windows.media.speech/recognizer.c new file mode 100644 index 00000000000..efb6c7a2a8e --- /dev/null +++ b/dlls/windows.media.speech/recognizer.c @@ -0,0 +1,253 @@ +/* WinRT Windows.Media.SpeechRecognition implementation + * + * Copyright 2022 Bernhard Kölbl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(speech); + +/* + * + * Statics for SpeechRecognizer + * + */ + +struct recognizer_statics +{ + IActivationFactory IActivationFactory_iface; + ISpeechRecognizerFactory ISpeechRecognizerFactory_iface; + ISpeechRecognizerStatics ISpeechRecognizerStatics_iface; + ISpeechRecognizerStatics2 ISpeechRecognizerStatics2_iface; + LONG ref; +}; + +/* + * + * IActivationFactory + * + */ + +static inline struct recognizer_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD(iface, struct recognizer_statics, IActivationFactory_iface); +} + +static HRESULT WINAPI activation_factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct recognizer_statics *impl = impl_from_IActivationFactory(iface); + + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_IAgileObject) || + IsEqualGUID(iid, &IID_IActivationFactory)) + { + IInspectable_AddRef((*out = &impl->IActivationFactory_iface)); + return S_OK; + } + + if (IsEqualGUID(iid, &IID_ISpeechRecognizerFactory)) + { + IInspectable_AddRef((*out = &impl->ISpeechRecognizerFactory_iface)); + return S_OK; + } + + if (IsEqualGUID(iid, &IID_ISpeechRecognizerStatics)) + { + IInspectable_AddRef((*out = &impl->ISpeechRecognizerStatics_iface)); + return S_OK; + } + + if (IsEqualGUID(iid, &IID_ISpeechRecognizerStatics2)) + { + IInspectable_AddRef((*out = &impl->ISpeechRecognizerStatics2_iface)); + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI activation_factory_AddRef( IActivationFactory *iface ) +{ + struct recognizer_statics *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI activation_factory_Release( IActivationFactory *iface ) +{ + struct recognizer_statics *impl = impl_from_IActivationFactory(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static HRESULT WINAPI activation_factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT WINAPI activation_factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI activation_factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT WINAPI activation_factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + TRACE("iface %p, instance %p\n", iface, instance); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl activation_factory_vtbl = +{ + /* IUnknown methods */ + activation_factory_QueryInterface, + activation_factory_AddRef, + activation_factory_Release, + /* IInspectable methods */ + activation_factory_GetIids, + activation_factory_GetRuntimeClassName, + activation_factory_GetTrustLevel, + /* IActivationFactory methods */ + activation_factory_ActivateInstance, +}; + +/* + * + * ISpeechRecognizerFactory + * + */ + +DEFINE_IINSPECTABLE(recognizer_factory, ISpeechRecognizerFactory, struct recognizer_statics, IActivationFactory_iface) + +static HRESULT WINAPI recognizer_factory_Create( ISpeechRecognizerFactory *iface, ILanguage *language, ISpeechRecognizer **speechrecognizer ) +{ + TRACE("iface %p, language %p, speechrecognizer %p.\n", iface, language, speechrecognizer); + return E_NOTIMPL; +} + +static const struct ISpeechRecognizerFactoryVtbl speech_recognizer_factory_vtbl = +{ + /* IUnknown methods */ + recognizer_factory_QueryInterface, + recognizer_factory_AddRef, + recognizer_factory_Release, + /* IInspectable methods */ + recognizer_factory_GetIids, + recognizer_factory_GetRuntimeClassName, + recognizer_factory_GetTrustLevel, + /* ISpeechRecognizerFactory methods */ + recognizer_factory_Create +}; + +/* + * + * ISpeechRecognizerStatics + * + */ + +DEFINE_IINSPECTABLE(statics, ISpeechRecognizerStatics, struct recognizer_statics, IActivationFactory_iface) + +static HRESULT WINAPI statics_get_SystemSpeechLanguage( ISpeechRecognizerStatics *iface, ILanguage **language ) +{ + FIXME("iface %p, language %p stub!\n", iface, language); + return E_NOTIMPL; +} + +static HRESULT WINAPI statics_get_SupportedTopicLanguages( ISpeechRecognizerStatics *iface, IVectorView_Language **languages ) +{ + FIXME("iface %p, languages %p stub!\n", iface, languages); + return E_NOTIMPL; +} + +static HRESULT WINAPI statics_get_SupportedGrammarLanguages( ISpeechRecognizerStatics *iface, IVectorView_Language **languages ) +{ + FIXME("iface %p, languages %p stub!\n", iface, languages); + return E_NOTIMPL; +} + +static const struct ISpeechRecognizerStaticsVtbl speech_recognizer_statics_vtbl = +{ + /* IUnknown methods */ + statics_QueryInterface, + statics_AddRef, + statics_Release, + /* IInspectable methods */ + statics_GetIids, + statics_GetRuntimeClassName, + statics_GetTrustLevel, + /* ISpeechRecognizerStatics2 methods */ + statics_get_SystemSpeechLanguage, + statics_get_SupportedTopicLanguages, + statics_get_SupportedGrammarLanguages +}; + +/* + * + * ISpeechRecognizerStatics2 + * + */ + +DEFINE_IINSPECTABLE(statics2, ISpeechRecognizerStatics2, struct recognizer_statics, IActivationFactory_iface) + +static HRESULT WINAPI statics2_TrySetSystemSpeechLanguageAsync( ISpeechRecognizerStatics2 *iface, + ILanguage *language, + IAsyncOperation_boolean **operation) +{ + FIXME("iface %p, operation %p stub!\n", iface, operation); + return E_NOTIMPL; +} + +static const struct ISpeechRecognizerStatics2Vtbl speech_recognizer_statics2_vtbl = +{ + /* IUnknown methods */ + statics2_QueryInterface, + statics2_AddRef, + statics2_Release, + /* IInspectable methods */ + statics2_GetIids, + statics2_GetRuntimeClassName, + statics2_GetTrustLevel, + /* ISpeechRecognizerStatics2 methods */ + statics2_TrySetSystemSpeechLanguageAsync, +}; + +static struct recognizer_statics recognizer_statics = +{ + .IActivationFactory_iface = {&activation_factory_vtbl}, + .ISpeechRecognizerFactory_iface = {&speech_recognizer_factory_vtbl}, + .ISpeechRecognizerStatics_iface = {&speech_recognizer_statics_vtbl}, + .ISpeechRecognizerStatics2_iface = {&speech_recognizer_statics2_vtbl}, + .ref = 1 +}; + +IActivationFactory *recognizer_factory = &recognizer_statics.IActivationFactory_iface; diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index be5499954be..23e36f1e0a8 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -108,7 +108,7 @@ static void test_ActivationFactory(void) check_refcount(factory2, 3);
hr = RoGetActivationFactory(str2, &IID_IActivationFactory, (void **)&factory3); - todo_wine ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "Got unexpected hr %#lx.\n", hr); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "Got unexpected hr %#lx.\n", hr);
if (hr == S_OK) /* Win10+ only */ {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=110268
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/recognizer.c | 304 ++++++++++++++++++++++++- 1 file changed, 302 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.media.speech/recognizer.c b/dlls/windows.media.speech/recognizer.c index efb6c7a2a8e..e5510d7677b 100644 --- a/dlls/windows.media.speech/recognizer.c +++ b/dlls/windows.media.speech/recognizer.c @@ -23,6 +23,285 @@
WINE_DEFAULT_DEBUG_CHANNEL(speech);
+/* + * + * SpeechRecognizer + * + */ + +struct recognizer +{ + ISpeechRecognizer ISpeechRecognizer_iface; + IClosable IClosable_iface; + ISpeechRecognizer2 ISpeechRecognizer2_iface; + LONG ref; +}; + +/* + * + * ISpeechRecognizer + * + */ + +static inline struct recognizer *impl_from_ISpeechRecognizer( ISpeechRecognizer *iface ) +{ + return CONTAINING_RECORD(iface, struct recognizer, ISpeechRecognizer_iface); +} + +static HRESULT WINAPI recognizer_QueryInterface( ISpeechRecognizer *iface, REFIID iid, void **out ) +{ + struct recognizer *impl = impl_from_ISpeechRecognizer(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_ISpeechRecognizer)) + { + IInspectable_AddRef((*out = &impl->ISpeechRecognizer_iface)); + return S_OK; + } + + if(IsEqualGUID(iid, &IID_IClosable)) + { + IInspectable_AddRef((*out = &impl->IClosable_iface)); + return S_OK; + } + + if(IsEqualGUID(iid, &IID_ISpeechRecognizer2)) + { + IInspectable_AddRef((*out = &impl->ISpeechRecognizer2_iface)); + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI recognizer_AddRef( ISpeechRecognizer *iface ) +{ + struct recognizer *impl = impl_from_ISpeechRecognizer(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI recognizer_Release( ISpeechRecognizer *iface ) +{ + struct recognizer *impl = impl_from_ISpeechRecognizer(iface); + + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + + if(!ref) + free(impl); + + return ref; +} + +static HRESULT WINAPI recognizer_GetIids( ISpeechRecognizer *iface, ULONG *iid_count, IID **iids ) +{ + FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_GetRuntimeClassName( ISpeechRecognizer *iface, HSTRING *class_name ) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_GetTrustLevel( ISpeechRecognizer *iface, TrustLevel *trust_level ) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_get_Constraints( ISpeechRecognizer *iface, IVector_ISpeechRecognitionConstraint **vector ) +{ + FIXME("iface %p, operation %p stub!\n", iface, vector); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_get_CurrentLanguage( ISpeechRecognizer *iface, ILanguage **language ) +{ + FIXME("iface %p, operation %p stub!\n", iface, language); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_get_Timeouts( ISpeechRecognizer *iface, ISpeechRecognizerTimeouts **timeouts ) +{ + FIXME("iface %p, operation %p stub!\n", iface, timeouts); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_get_UIOptions( ISpeechRecognizer *iface, ISpeechRecognizerUIOptions **options ) +{ + FIXME("iface %p, operation %p stub!\n", iface, options); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_CompileConstraintsAsync( ISpeechRecognizer *iface, + IAsyncOperation_SpeechRecognitionCompilationResult **operation ) +{ + FIXME("iface %p, operation %p stub!\n", iface, operation); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_RecognizeAsync( ISpeechRecognizer *iface, + IAsyncOperation_SpeechRecognitionResult **operation ) +{ + FIXME("iface %p, operation %p stub!\n", iface, operation); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_RecognizeWithUIAsync( ISpeechRecognizer *iface, + IAsyncOperation_SpeechRecognitionResult **operation ) +{ + FIXME("iface %p, operation %p stub!\n", iface, operation); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_add_RecognitionQualityDegrading( ISpeechRecognizer *iface, + ITypedEventHandler_SpeechRecognizer_SpeechRecognitionQualityDegradingEventArgs *handler, + EventRegistrationToken *token ) +{ + FIXME("iface %p, operation %p, token %p, stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_remove_RecognitionQualityDegrading( ISpeechRecognizer *iface, EventRegistrationToken token ) +{ + FIXME("iface %p, token.value %#I64x, stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_add_StateChanged( ISpeechRecognizer *iface, + ITypedEventHandler_SpeechRecognizer_SpeechRecognizerStateChangedEventArgs *handler, + EventRegistrationToken *token ) +{ + FIXME("iface %p, operation %p, token %p, stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer_remove_StateChanged( ISpeechRecognizer *iface, EventRegistrationToken token ) +{ + FIXME("iface %p, token.value %#I64x, stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static const struct ISpeechRecognizerVtbl speech_recognizer_vtbl = +{ + /* IUnknown methods */ + recognizer_QueryInterface, + recognizer_AddRef, + recognizer_Release, + /* IInspectable methods */ + recognizer_GetIids, + recognizer_GetRuntimeClassName, + recognizer_GetTrustLevel, + /* ISpeechRecognizer methods */ + recognizer_get_CurrentLanguage, + recognizer_get_Constraints, + recognizer_get_Timeouts, + recognizer_get_UIOptions, + recognizer_CompileConstraintsAsync, + recognizer_RecognizeAsync, + recognizer_RecognizeWithUIAsync, + recognizer_add_RecognitionQualityDegrading, + recognizer_remove_RecognitionQualityDegrading, + recognizer_add_StateChanged, + recognizer_remove_StateChanged, +}; + +/* + * + * IClosable + * + */ + +DEFINE_IINSPECTABLE(closable, IClosable, struct recognizer, ISpeechRecognizer_iface) + +static HRESULT WINAPI closable_Close( IClosable *iface ) +{ + FIXME("iface %p stub.\n", iface); + return E_NOTIMPL; +} + +static const struct IClosableVtbl closable_vtbl = +{ + /* IUnknown methods */ + closable_QueryInterface, + closable_AddRef, + closable_Release, + /* IInspectable methods */ + closable_GetIids, + closable_GetRuntimeClassName, + closable_GetTrustLevel, + /* IClosable methods */ + closable_Close, +}; + +/* + * + * ISpeechRecognizer2 + * + */ + +DEFINE_IINSPECTABLE(recognizer2, ISpeechRecognizer2, struct recognizer, ISpeechRecognizer_iface) + +static HRESULT WINAPI recognizer2_get_ContinuousRecognitionSession( ISpeechRecognizer2 *iface, + ISpeechContinuousRecognitionSession **session ) +{ + FIXME("iface %p, session %p stub!\n", iface, session); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer2_get_State( ISpeechRecognizer2 *iface, SpeechRecognizerState *state ) +{ + FIXME("iface %p, state %p stub!\n", iface, state); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer2_StopRecognitionAsync( ISpeechRecognizer2 *iface, IAsyncAction **action ) +{ + FIXME("iface %p, action %p stub!\n", iface, action); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer2_add_HypothesisGenerated( ISpeechRecognizer2 *iface, + ITypedEventHandler_SpeechRecognizer_SpeechRecognitionHypothesisGeneratedEventArgs *handler, + EventRegistrationToken *token ) +{ + FIXME("iface %p, operation %p, token %p, stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI recognizer2_remove_HypothesisGenerated( ISpeechRecognizer2 *iface, EventRegistrationToken token ) +{ + FIXME("iface %p, token.value %#I64x, stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static const struct ISpeechRecognizer2Vtbl speech_recognizer2_vtbl = +{ + /* IUnknown methods */ + recognizer2_QueryInterface, + recognizer2_AddRef, + recognizer2_Release, + /* IInspectable methods */ + recognizer2_GetIids, + recognizer2_GetRuntimeClassName, + recognizer2_GetTrustLevel, + /* ISpeechRecognizer2 methods */ + recognizer2_get_ContinuousRecognitionSession, + recognizer2_get_State, + recognizer2_StopRecognitionAsync, + recognizer2_add_HypothesisGenerated, + recognizer2_remove_HypothesisGenerated, +}; + /* * * Statics for SpeechRecognizer @@ -123,8 +402,9 @@ static HRESULT WINAPI activation_factory_GetTrustLevel( IActivationFactory *ifac
static HRESULT WINAPI activation_factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) { + struct recognizer_statics *impl = impl_from_IActivationFactory(iface); TRACE("iface %p, instance %p\n", iface, instance); - return E_NOTIMPL; + return ISpeechRecognizerFactory_Create(&impl->ISpeechRecognizerFactory_iface, NULL, (ISpeechRecognizer **)instance); }
static const struct IActivationFactoryVtbl activation_factory_vtbl = @@ -151,8 +431,28 @@ DEFINE_IINSPECTABLE(recognizer_factory, ISpeechRecognizerFactory, struct recogni
static HRESULT WINAPI recognizer_factory_Create( ISpeechRecognizerFactory *iface, ILanguage *language, ISpeechRecognizer **speechrecognizer ) { + struct recognizer *impl; + TRACE("iface %p, language %p, speechrecognizer %p.\n", iface, language, speechrecognizer); - return E_NOTIMPL; + + if (!(impl = calloc(1, sizeof(*impl)))) + { + *speechrecognizer = NULL; + return E_OUTOFMEMORY; + } + + if(language) + FIXME("ILanguage parameter unused. Stub!\n"); + + impl->ISpeechRecognizer_iface.lpVtbl = &speech_recognizer_vtbl; + impl->IClosable_iface.lpVtbl = &closable_vtbl; + impl->ISpeechRecognizer2_iface.lpVtbl = &speech_recognizer2_vtbl; + impl->ref = 1; + + TRACE("created SpeechRecognizer %p\n", impl); + + *speechrecognizer = &impl->ISpeechRecognizer_iface; + return S_OK; }
static const struct ISpeechRecognizerFactoryVtbl speech_recognizer_factory_vtbl =
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=110269
Your paranoid android.
=== debian11 (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 117 +++++++++++++++++++++++ 1 file changed, 117 insertions(+)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 23e36f1e0a8..9e4f031a55f 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -29,6 +29,8 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Globalization +#include "windows.globalization.h" #define WIDL_using_Windows_Media_SpeechRecognition #include "windows.media.speechrecognition.h" #define WIDL_using_Windows_Media_SpeechSynthesis @@ -66,6 +68,15 @@ static void check_interface_(unsigned int line, void *obj, const IID *iid, BOOL IUnknown_Release(unk); }
+static const char *debugstr_hstring(HSTRING hstr) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer(hstr, &len); + return wine_dbgstr_wn(str, len); +} + static void test_ActivationFactory(void) { static const WCHAR *synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer"; @@ -328,9 +339,115 @@ static void test_VoiceInformation(void) RoUninitialize(); }
+static void test_SpeechRecognizer(void) +{ + static const WCHAR *speech_recognition_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer"; + ISpeechRecognizerFactory *sr_factory = NULL; + ISpeechRecognizerStatics *sr_statics = NULL; + ISpeechRecognizerStatics2 *sr_statics2 = NULL; + ISpeechRecognizer *recognizer = NULL; + ISpeechRecognizer2 *recognizer2 = NULL; + IActivationFactory *factory = NULL; + IInspectable *inspectable = NULL; + IClosable *closable = NULL; + ILanguage *language = NULL; + HSTRING hstr, hstr_lang; + HRESULT hr; + LONG ref; + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "RoInitialize failed, hr %#lx.\n", hr); + + hr = WindowsCreateString(speech_recognition_name, wcslen(speech_recognition_name), &hstr); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.n", hr); + + hr = RoGetActivationFactory(hstr, &IID_IActivationFactory, (void **)&factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr); + + if(hr == REGDB_E_CLASSNOTREG) /* Win 8 and 8.1 */ + { + win_skip("SpeechRecognizer activation factory not available!\n"); + goto done; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechRecognizerFactory, (void **)&sr_factory); + ok(hr == S_OK, "IActivationFactory_QueryInterface IID_ISpeechRecognizer failed, hr %#lx.\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechRecognizerStatics, (void **)&sr_statics); + ok(hr == S_OK, "IActivationFactory_QueryInterface IID_ISpeechRecognizerStatics failed, hr %#lx.\n", hr); + + hr = ISpeechRecognizerStatics_get_SystemSpeechLanguage(sr_statics, &language); + todo_wine ok(hr == S_OK, "ISpeechRecognizerStatics_SystemSpeechLanguage failed, hr %#lx.\n", hr); + + if(hr == S_OK) + { + hr = ILanguage_get_LanguageTag(language, &hstr_lang); + ok(hr == S_OK, "ILanguage_get_LanguageTag failed, hr %#lx.\n", hr); + + trace("SpeechRecognizer default language %s.\n", debugstr_hstring(hstr_lang)); + + ILanguage_Release(language); + } + + ref = ISpeechRecognizerStatics_Release(sr_statics); + ok(ref == 3, "Got unexpected ref %lu.\n", ref); + + hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechRecognizerStatics2, (void **)&sr_statics2); + ok(hr == S_OK || broken(hr == E_NOINTERFACE), "IActivationFactory_QueryInterface IID_ISpeechRecognizerStatics2 failed, hr %#lx.\n", hr); + + if(hr == S_OK) /* SpeechRecognizerStatics2 not implemented on Win10 1507 */ + { + ref = ISpeechRecognizerStatics2_Release(sr_statics2); + ok(ref == 3, "Got unexpected ref %lu.\n", ref); + } + + ref = ISpeechRecognizerFactory_Release(sr_factory); + ok(ref == 2, "Got unexpected ref %lu.\n", ref); + + ref = IActivationFactory_Release(factory); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + hr = RoActivateInstance(hstr, &inspectable); + ok(hr == S_OK || broken(hr == 0x800455a0), "Got unexpected hr %#lx.\n", hr); + + if(hr == S_OK) + { + hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer, (void **)&recognizer); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer2, (void **)&recognizer2); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IInspectable_QueryInterface(inspectable, &IID_IClosable, (void **)&closable); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + ref = IClosable_Release(closable); + ok(ref == 3, "Got unexpected ref %lu.\n", ref); + + ref = ISpeechRecognizer2_Release(recognizer2); + ok(ref == 2, "Got unexpected ref %lu.\n", ref); + + ref = ISpeechRecognizer_Release(recognizer); + ok(ref == 1, "Got unexpected ref %lu.\n", ref); + + ref = IInspectable_Release(inspectable); + ok(!ref, "Got unexpected ref %lu.\n", ref); + } + else if(hr == 0x800455a0) /* Not sure what this hr is... Probably if a language pack is not installed. */ + { + win_skip("Could not init SpeechRecognizer with default language!\n"); + } + +done: + WindowsDeleteString(hstr); + + RoUninitialize(); +} + START_TEST(speech) { test_ActivationFactory(); test_SpeechSynthesizer(); test_VoiceInformation(); + test_SpeechRecognizer(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=110270
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/windows.media.speech/tests/speech.c:108 Task: Patch failed to apply
On 3/10/22 18:35, Bernhard Kölbl wrote:
Signed-off-by: Bernhard Kölbl besentv@gmail.com
dlls/windows.media.speech/tests/speech.c | 117 +++++++++++++++++++++++ 1 file changed, 117 insertions(+)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 23e36f1e0a8..9e4f031a55f 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -29,6 +29,8 @@ #define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections #include "windows.foundation.h" +#define WIDL_using_Windows_Globalization +#include "windows.globalization.h" #define WIDL_using_Windows_Media_SpeechRecognition #include "windows.media.speechrecognition.h" #define WIDL_using_Windows_Media_SpeechSynthesis @@ -66,6 +68,15 @@ static void check_interface_(unsigned int line, void *obj, const IID *iid, BOOL IUnknown_Release(unk); }
+static const char *debugstr_hstring(HSTRING hstr) +{
- const WCHAR *str;
- UINT32 len;
- if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)";
- str = WindowsGetStringRawBuffer(hstr, &len);
- return wine_dbgstr_wn(str, len);
+}
- static void test_ActivationFactory(void) { static const WCHAR *synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer";
@@ -328,9 +339,115 @@ static void test_VoiceInformation(void) RoUninitialize(); }
+static void test_SpeechRecognizer(void) +{
- static const WCHAR *speech_recognition_name = L"Windows.Media.SpeechRecognition.SpeechRecognizer";
- ISpeechRecognizerFactory *sr_factory = NULL;
- ISpeechRecognizerStatics *sr_statics = NULL;
- ISpeechRecognizerStatics2 *sr_statics2 = NULL;
- ISpeechRecognizer *recognizer = NULL;
- ISpeechRecognizer2 *recognizer2 = NULL;
- IActivationFactory *factory = NULL;
- IInspectable *inspectable = NULL;
- IClosable *closable = NULL;
- ILanguage *language = NULL;
- HSTRING hstr, hstr_lang;
- HRESULT hr;
- LONG ref;
- hr = RoInitialize(RO_INIT_MULTITHREADED);
- ok(hr == S_OK, "RoInitialize failed, hr %#lx.\n", hr);
- hr = WindowsCreateString(speech_recognition_name, wcslen(speech_recognition_name), &hstr);
- ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.n", hr);
- hr = RoGetActivationFactory(hstr, &IID_IActivationFactory, (void **)&factory);
- ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "RoGetActivationFactory failed, hr %#lx.\n", hr);
- if(hr == REGDB_E_CLASSNOTREG) /* Win 8 and 8.1 */
- {
win_skip("SpeechRecognizer activation factory not available!\n");
goto done;
- }
- hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechRecognizerFactory, (void **)&sr_factory);
- ok(hr == S_OK, "IActivationFactory_QueryInterface IID_ISpeechRecognizer failed, hr %#lx.\n", hr);
- hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechRecognizerStatics, (void **)&sr_statics);
- ok(hr == S_OK, "IActivationFactory_QueryInterface IID_ISpeechRecognizerStatics failed, hr %#lx.\n", hr);
- hr = ISpeechRecognizerStatics_get_SystemSpeechLanguage(sr_statics, &language);
- todo_wine ok(hr == S_OK, "ISpeechRecognizerStatics_SystemSpeechLanguage failed, hr %#lx.\n", hr);
- if(hr == S_OK)
- {
hr = ILanguage_get_LanguageTag(language, &hstr_lang);
ok(hr == S_OK, "ILanguage_get_LanguageTag failed, hr %#lx.\n", hr);
trace("SpeechRecognizer default language %s.\n", debugstr_hstring(hstr_lang));
ILanguage_Release(language);
- }
- ref = ISpeechRecognizerStatics_Release(sr_statics);
- ok(ref == 3, "Got unexpected ref %lu.\n", ref);
- hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechRecognizerStatics2, (void **)&sr_statics2);
- ok(hr == S_OK || broken(hr == E_NOINTERFACE), "IActivationFactory_QueryInterface IID_ISpeechRecognizerStatics2 failed, hr %#lx.\n", hr);
- if(hr == S_OK) /* SpeechRecognizerStatics2 not implemented on Win10 1507 */
- {
ref = ISpeechRecognizerStatics2_Release(sr_statics2);
ok(ref == 3, "Got unexpected ref %lu.\n", ref);
- }
- ref = ISpeechRecognizerFactory_Release(sr_factory);
- ok(ref == 2, "Got unexpected ref %lu.\n", ref);
- ref = IActivationFactory_Release(factory);
- ok(ref == 1, "Got unexpected ref %lu.\n", ref);
- hr = RoActivateInstance(hstr, &inspectable);
- ok(hr == S_OK || broken(hr == 0x800455a0), "Got unexpected hr %#lx.\n", hr);
- if(hr == S_OK)
- {
hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer, (void **)&recognizer);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechRecognizer2, (void **)&recognizer2);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IInspectable_QueryInterface(inspectable, &IID_IClosable, (void **)&closable);
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
ref = IClosable_Release(closable);
ok(ref == 3, "Got unexpected ref %lu.\n", ref);
ref = ISpeechRecognizer2_Release(recognizer2);
ok(ref == 2, "Got unexpected ref %lu.\n", ref);
ref = ISpeechRecognizer_Release(recognizer);
ok(ref == 1, "Got unexpected ref %lu.\n", ref);
ref = IInspectable_Release(inspectable);
ok(!ref, "Got unexpected ref %lu.\n", ref);
- }
- else if(hr == 0x800455a0) /* Not sure what this hr is... Probably if a language pack is not installed. */
- {
win_skip("Could not init SpeechRecognizer with default language!\n");
- }
+done:
- WindowsDeleteString(hstr);
- RoUninitialize();
+}
- START_TEST(speech) { test_ActivationFactory(); test_SpeechSynthesizer(); test_VoiceInformation();
- test_SpeechRecognizer(); }
Looks like 0x800455a0 is some kind of generic error, google results suggest SPERR_WINRT_INTERNAL_ERROR though it's probably not worth defining it.
Also, it's usually preferred to add tests first, then add the implementation. This makes sure that the implementation gets a bit tested as soon as it is introduced, and with todo_wine addition/removal it gets clear what is now implemented and what isn't.
Cheers,
Hi Bernhard,
As you probably figured you will need to either wait for the long conversion patch to be applied, or send it before these, and combined in the series.
Also, while you're at it, you probably should merge the first patch here with the second which uses the macro, so that you don't add dead code (even a macro). It's probably okay if it is in a completely separate place, like adding something to the public header, then use it separately, but in a private source we try to avoid it.
Cheers,
Hi Rémi,
yeah I totally forgot, that the other patch needs to be applied first. I'll merge the first 2 patches as well.
Bernhard
Rémi Bernon rbernon@codeweavers.com schrieb am Do., 10. März 2022, 18:44:
Hi Bernhard,
As you probably figured you will need to either wait for the long conversion patch to be applied, or send it before these, and combined in the series.
Also, while you're at it, you probably should merge the first patch here with the second which uses the macro, so that you don't add dead code (even a macro). It's probably okay if it is in a completely separate place, like adding something to the public header, then use it separately, but in a private source we try to avoid it.
Cheers,
Rémi Bernon rbernon@codeweavers.com