Signed-off-by: Bernhard Kölbl besentv@gmail.com
-- v3: windows.media.speech: Add stub ISpeechSynthesisStream iface. windows.media.speech: Return IAsyncOperation from synthesizer_SynthesizeSsmlToStreamAsync. windows.media.speech: Return IAsyncOperation from synthesizer_SynthesizeTextToStreamAsync. windows.media.speech/tests: Add basic tests for ssml/text to stream functions. windows.media.speech/tests: Handle a possible race condition.
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 5e74b90bf9a..421819fd10a 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -331,7 +331,6 @@ struct async_inspectable_handler
HANDLE event_block; HANDLE event_finished; - DWORD thread_id; };
static inline struct async_inspectable_handler *impl_from_IAsyncOperationCompletedHandler_IInspectable( IAsyncOperationCompletedHandler_IInspectable *iface ) @@ -378,9 +377,8 @@ HRESULT WINAPI async_inspectable_handler_Invoke( IAsyncOperationCompletedHandler AsyncStatus status ) { struct async_inspectable_handler *impl = impl_from_IAsyncOperationCompletedHandler_IInspectable(iface); - DWORD id = GetCurrentThreadId(); + trace("Iface %p, sender %p, status %d.\n", iface, sender, status); - trace("Caller thread id %lu callback thread id %lu.\n", impl->thread_id, id);
/* Signal finishing of the handler. */ if (impl->event_finished) SetEvent(impl->event_finished); @@ -1217,7 +1215,6 @@ static void test_SpeechRecognizer(void) async_inspectable_handler_create_static(&compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); compilation_handler.event_block = CreateEventW(NULL, FALSE, FALSE, NULL); compilation_handler.event_finished = CreateEventW(NULL, FALSE, FALSE, NULL); - compilation_handler.thread_id = GetCurrentThreadId();
ok(!!compilation_handler.event_block, "event_block wasn't created.\n"); ok(!!compilation_handler.event_finished, "event_finished wasn't created.\n");
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 421819fd10a..d1e1c0cc396 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -1122,13 +1122,15 @@ static void test_SpeechRecognizer(void)
compilation_result = (void*)0xdeadbeef; hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result); + if (hr == S_OK) /* Sometimes the operation could have already finished here, */ + goto skip_await; /* if so skip waiting and getting the results a second time. */ + ok(hr == E_ILLEGAL_METHOD_CALL, "Got unexpected hr %#lx.\n", hr); ok(compilation_result == (void*)0xdeadbeef, "Compilation result had value %p.\n", compilation_result);
await_async_inspectable((IAsyncOperation_IInspectable *)operation, &compilation_handler, &IID_IAsyncOperationCompletedHandler_SpeechRecognitionCompilationResult); - check_async_info((IInspectable *)operation, 1, Completed, S_OK);
hr = IAsyncOperation_SpeechRecognitionCompilationResult_put_Completed(operation, NULL); ok(hr == E_ILLEGAL_DELEGATE_ASSIGNMENT, "Got unexpected hr %#lx.\n", hr); @@ -1138,10 +1140,13 @@ static void test_SpeechRecognizer(void)
compilation_result = (void*)0xdeadbeef; hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result); +skip_await: ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
check_interface(compilation_result, &IID_IAgileObject, TRUE);
+ check_async_info((IInspectable *)operation, 1, Completed, S_OK); + hr = ISpeechRecognitionCompilationResult_get_Status(compilation_result, &result_status); ok(hr == S_OK, "ISpeechRecognitionCompilationResult_get_Status failed, hr %#lx.\n", hr); ok(result_status == SpeechRecognitionResultStatus_Success, "Got unexpected status %#x.\n", result_status);
From: Bernhard Kölbl besentv@gmail.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/tests/speech.c | 82 ++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 5 deletions(-)
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index d1e1c0cc396..01543c145e3 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -779,18 +779,26 @@ static void test_ActivationFactory(void)
static void test_SpeechSynthesizer(void) { + static const WCHAR *simple_ssml = + L"<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis' xml:lang='en-US'>" + "Hello, how are you doing today?" + "</speak>"; + static const WCHAR *simple_synth_text = L"Hello, how are you doing today?"; static const WCHAR *speech_synthesizer_name = L"Windows.Media.SpeechSynthesis.SpeechSynthesizer"; static const WCHAR *speech_synthesizer_name2 = L"windows.media.speechsynthesis.speechsynthesizer"; static const WCHAR *unknown_class_name = L"Unknown.Class"; IActivationFactory *factory = NULL, *factory2 = NULL; + IAsyncOperation_SpeechSynthesisStream *operation_ss_stream = NULL; IVectorView_VoiceInformation *voices = NULL; IInstalledVoicesStatic *voices_static = NULL; + ISpeechSynthesisStream *ss_stream = NULL; IVoiceInformation *voice; IInspectable *inspectable = NULL, *tmp_inspectable = NULL; IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; ISpeechSynthesizer *synthesizer; ISpeechSynthesizer2 *synthesizer2; IClosable *closable; + struct async_inspectable_handler async_inspectable_handler; HMODULE hdll; HSTRING str, str2; HRESULT hr; @@ -843,6 +851,7 @@ static void test_SpeechSynthesizer(void) FreeLibrary(hdll); }
+ /* Test static Synth ifaces: IActivationFactory, IInstalledVoicesStatic, etc. */ hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable); ok(hr == S_OK, "IActivationFactory_QueryInterface IID_IInspectable failed, hr %#lx\n", hr);
@@ -889,27 +898,91 @@ static void test_SpeechSynthesizer(void)
IVectorView_VoiceInformation_Release(voices);
- IInstalledVoicesStatic_Release(voices_static); + hr = IInstalledVoicesStatic_get_DefaultVoice(voices_static, &voice); + todo_wine ok(hr == S_OK, "IInstalledVoicesStatic_get_DefaultVoice failed, hr %#lx\n", hr); + + if (hr == S_OK) + { + IVoiceInformation_get_Description(voice, &str2); + trace("SpeechSynthesizer default voice %s.\n", debugstr_hstring(str2));
+ WindowsDeleteString(str2); + ref = IVoiceInformation_Release(voice); + ok(ref == 0, "Got unexpected ref %lu.\n", ref); + } + + IInstalledVoicesStatic_Release(voices_static); IAgileObject_Release(agile_object); IInspectable_Release(inspectable);
+ /* Test Synthesizer */ hr = IActivationFactory_QueryInterface(factory, &IID_ISpeechSynthesizer, (void **)&synthesizer); ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
hr = RoActivateInstance(str, &inspectable); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + WindowsDeleteString(str);
hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechSynthesizer, (void **)&synthesizer); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
+ /* Test SynthesizeTextToStreamAsync */ + hr = WindowsCreateString(simple_synth_text, wcslen(simple_synth_text), &str); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx\n", hr); + + hr = ISpeechSynthesizer_SynthesizeTextToStreamAsync(synthesizer, str, &operation_ss_stream); + todo_wine ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); + if(FAILED(hr)) goto skip_ss_stream; + + await_async_inspectable((IAsyncOperation_IInspectable *)operation_ss_stream, + &async_inspectable_handler, + &IID_IAsyncOperationCompletedHandler_SpeechSynthesisStream); + check_async_info((IInspectable *)operation_ss_stream, 1, Completed, S_OK); + check_interface(operation_ss_stream, &IID_IAgileObject, TRUE); + + hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &ss_stream); + todo_wine ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr); + + if (hr == S_OK && ss_stream) + { + ref = ISpeechSynthesisStream_Release(ss_stream); + todo_wine ok(ref == 0, "Got unexpected ref %lu.\n", ref); + } + + IAsyncOperation_SpeechSynthesisStream_Release(operation_ss_stream); + WindowsDeleteString(str); + + /* Test SynthesizeSsmlToStreamAsync */ + hr = WindowsCreateString(simple_ssml, wcslen(simple_ssml), &str); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx\n", hr); + + hr = ISpeechSynthesizer_SynthesizeSsmlToStreamAsync(synthesizer, str, &operation_ss_stream); + todo_wine ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); + await_async_inspectable((IAsyncOperation_IInspectable *)operation_ss_stream, + &async_inspectable_handler, + &IID_IAsyncOperationCompletedHandler_SpeechSynthesisStream); + check_async_info((IInspectable *)operation_ss_stream, 2, Completed, S_OK); + check_interface(operation_ss_stream, &IID_IAgileObject, TRUE); + + hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &ss_stream); + todo_wine ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr); + + if (hr == S_OK && ss_stream) + { + ref = ISpeechSynthesisStream_Release(ss_stream); + ok(ref == 0, "Got unexpected ref %lu.\n", ref); + } + + IAsyncOperation_SpeechSynthesisStream_Release(operation_ss_stream); + +skip_ss_stream: + WindowsDeleteString(str); + hr = IInspectable_QueryInterface(inspectable, &IID_IClosable, (void **)&closable); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
hr = IInspectable_QueryInterface(inspectable, &IID_ISpeechSynthesizer2, (void **)&synthesizer2); - ok(hr == S_OK || - broken(hr == E_NOINTERFACE), /* requires newer Windows */ - "Got unexpected hr %#lx.\n", hr); + ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Got unexpected hr %#lx.\n", hr); /* Requires Win10 >= 1703 */
if (hr == S_OK) { @@ -927,7 +1000,6 @@ static void test_SpeechSynthesizer(void) ok(!ref, "Got unexpected ref %lu.\n", ref);
IActivationFactory_Release(factory); - WindowsDeleteString(str);
RoUninitialize(); }
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=116592
Your paranoid android.
=== w8adm (32 bit report) ===
windows.media.speech: 0c7c:speech: unhandled exception c0000005 at 69FDB682
From: Bernhard Kölbl besentv@gmail.com
Based on a patch by: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/synthesizer.c | 8 +++++++- dlls/windows.media.speech/tests/speech.c | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index e8c9f0a280d..9275aa18c67 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -241,11 +241,17 @@ static HRESULT WINAPI synthesizer_GetTrustLevel( ISpeechSynthesizer *iface, Trus return E_NOTIMPL; }
+static HRESULT CALLBACK text_to_stream_operation( IInspectable *invoker, IInspectable **result ) +{ + return S_OK; +} + static HRESULT WINAPI synthesizer_SynthesizeTextToStreamAsync( ISpeechSynthesizer *iface, HSTRING text, IAsyncOperation_SpeechSynthesisStream **operation ) { FIXME("iface %p, text %p, operation %p stub.\n", iface, text, operation); - return E_NOTIMPL; + async_operation_inspectable_create(&IID_ISpeechSynthesisStream, NULL, text_to_stream_operation, (IAsyncOperation_IInspectable **)operation); + return S_OK; }
static HRESULT WINAPI synthesizer_SynthesizeSsmlToStreamAsync( ISpeechSynthesizer *iface, HSTRING ssml, diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 01543c145e3..8c584264fee 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -931,9 +931,7 @@ static void test_SpeechSynthesizer(void) ok(hr == S_OK, "WindowsCreateString failed, hr %#lx\n", hr);
hr = ISpeechSynthesizer_SynthesizeTextToStreamAsync(synthesizer, str, &operation_ss_stream); - todo_wine ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); - if(FAILED(hr)) goto skip_ss_stream; - + ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); await_async_inspectable((IAsyncOperation_IInspectable *)operation_ss_stream, &async_inspectable_handler, &IID_IAsyncOperationCompletedHandler_SpeechSynthesisStream); @@ -958,6 +956,8 @@ static void test_SpeechSynthesizer(void)
hr = ISpeechSynthesizer_SynthesizeSsmlToStreamAsync(synthesizer, str, &operation_ss_stream); todo_wine ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); + if(FAILED(hr)) goto skip_ss_stream; + await_async_inspectable((IAsyncOperation_IInspectable *)operation_ss_stream, &async_inspectable_handler, &IID_IAsyncOperationCompletedHandler_SpeechSynthesisStream);
From: Bernhard Kölbl besentv@gmail.com
Based on a patch by: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/synthesizer.c | 8 +++++++- dlls/windows.media.speech/tests/speech.c | 6 +----- 2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 9275aa18c67..22f28433216 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -254,11 +254,17 @@ static HRESULT WINAPI synthesizer_SynthesizeTextToStreamAsync( ISpeechSynthesize return S_OK; }
+static HRESULT CALLBACK ssml_to_stream_operation( IInspectable *invoker, IInspectable **result ) +{ + return S_OK; +} + static HRESULT WINAPI synthesizer_SynthesizeSsmlToStreamAsync( ISpeechSynthesizer *iface, HSTRING ssml, IAsyncOperation_SpeechSynthesisStream **operation ) { FIXME("iface %p, text %p, operation %p stub.\n", iface, ssml, operation); - return E_NOTIMPL; + async_operation_inspectable_create(&IID_ISpeechSynthesisStream, NULL, ssml_to_stream_operation, (IAsyncOperation_IInspectable **)operation); + return S_OK; }
static HRESULT WINAPI synthesizer_put_Voice( ISpeechSynthesizer *iface, IVoiceInformation *value ) diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 8c584264fee..4dd1fd7d14c 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -955,9 +955,7 @@ static void test_SpeechSynthesizer(void) ok(hr == S_OK, "WindowsCreateString failed, hr %#lx\n", hr);
hr = ISpeechSynthesizer_SynthesizeSsmlToStreamAsync(synthesizer, str, &operation_ss_stream); - todo_wine ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); - if(FAILED(hr)) goto skip_ss_stream; - + ok(hr == S_OK, "ISpeechSynthesizer_SynthesizeSsmlToStreamAsync failed, hr %#lx\n", hr); await_async_inspectable((IAsyncOperation_IInspectable *)operation_ss_stream, &async_inspectable_handler, &IID_IAsyncOperationCompletedHandler_SpeechSynthesisStream); @@ -974,8 +972,6 @@ static void test_SpeechSynthesizer(void) }
IAsyncOperation_SpeechSynthesisStream_Release(operation_ss_stream); - -skip_ss_stream: WindowsDeleteString(str);
hr = IInspectable_QueryInterface(inspectable, &IID_IClosable, (void **)&closable);
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=116594
Your paranoid android.
=== w8adm (32 bit report) ===
windows.media.speech: 0bac:speech: unhandled exception c0000005 at 6A25B682
From: Bernhard Kölbl besentv@gmail.com
Based on a patch by: Connor McAdams cmcadams@codeweavers.com
Silences a warning about narrator being broken in Forza Horizon 5.
Signed-off-by: Bernhard Kölbl besentv@gmail.com --- dlls/windows.media.speech/synthesizer.c | 126 ++++++++++++++++++++++- dlls/windows.media.speech/tests/speech.c | 18 ++-- 2 files changed, 128 insertions(+), 16 deletions(-)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 22f28433216..bf30dbf0847 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -146,6 +146,124 @@ static struct voice_information_vector all_voices = 0 };
+/* + * + * ISpeechSynthesisStream + * + */ + +struct synthesis_stream +{ + ISpeechSynthesisStream ISpeechSynthesisStream_iface; + LONG ref; +}; + +static inline struct synthesis_stream *impl_from_ISpeechSynthesisStream( ISpeechSynthesisStream *iface ) +{ + return CONTAINING_RECORD(iface, struct synthesis_stream, ISpeechSynthesisStream_iface); +} + +HRESULT WINAPI synthesis_stream_QueryInterface( ISpeechSynthesisStream *iface, REFIID iid, void **out ) +{ + struct synthesis_stream *impl = impl_from_ISpeechSynthesisStream(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_ISpeechSynthesisStream)) + { + IInspectable_AddRef((*out = &impl->ISpeechSynthesisStream_iface)); + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +ULONG WINAPI synthesis_stream_AddRef( ISpeechSynthesisStream *iface ) +{ + struct synthesis_stream *impl = impl_from_ISpeechSynthesisStream(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +ULONG WINAPI synthesis_stream_Release( ISpeechSynthesisStream *iface ) +{ + struct synthesis_stream *impl = impl_from_ISpeechSynthesisStream(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + free(impl); + + return ref; +} + +HRESULT WINAPI synthesis_stream_GetIids( ISpeechSynthesisStream *iface, ULONG *iid_count, IID **iids ) +{ + FIXME("iface %p, iid_count %p, iids %p stub.\n", iface, iid_count, iids); + return E_NOTIMPL; +} + +HRESULT WINAPI synthesis_stream_GetRuntimeClassName( ISpeechSynthesisStream *iface, HSTRING *class_name ) +{ + FIXME("iface %p, class_name %p stub.\n", iface, class_name); + return E_NOTIMPL; +} + +HRESULT WINAPI synthesis_stream_GetTrustLevel( ISpeechSynthesisStream *iface, TrustLevel *trust_level ) +{ + FIXME("iface %p, trust_level %p stub.\n", iface, trust_level); + return E_NOTIMPL; +} + +HRESULT WINAPI synthesis_stream_get_Markers( ISpeechSynthesisStream *iface, IVectorView_IMediaMarker **value ) +{ + FIXME("iface %p, value %p stub!\n", iface, value); + *value = NULL; + return S_OK; +} + +static const struct ISpeechSynthesisStreamVtbl synthesis_stream_vtbl = +{ + /* IUnknown methods */ + synthesis_stream_QueryInterface, + synthesis_stream_AddRef, + synthesis_stream_Release, + /* IInspectable methods */ + synthesis_stream_GetIids, + synthesis_stream_GetRuntimeClassName, + synthesis_stream_GetTrustLevel, + /* ISpeechSynthesisStream methods */ + synthesis_stream_get_Markers +}; + + +static HRESULT synthesis_stream_create( ISpeechSynthesisStream **out ) +{ + struct synthesis_stream *impl; + + TRACE("out %p.\n", out); + + if (!(impl = calloc(1, sizeof(*impl)))) + { + *out = NULL; + return E_OUTOFMEMORY; + } + + impl->ISpeechSynthesisStream_iface.lpVtbl = &synthesis_stream_vtbl; + impl->ref = 1; + + TRACE("created ISpeechSynthesisStream %p.\n", impl); + *out = &impl->ISpeechSynthesisStream_iface; + return S_OK; +} + /* * * SpeechSynthesizer runtimeclass @@ -243,26 +361,26 @@ static HRESULT WINAPI synthesizer_GetTrustLevel( ISpeechSynthesizer *iface, Trus
static HRESULT CALLBACK text_to_stream_operation( IInspectable *invoker, IInspectable **result ) { - return S_OK; + return synthesis_stream_create((ISpeechSynthesisStream **)result); }
static HRESULT WINAPI synthesizer_SynthesizeTextToStreamAsync( ISpeechSynthesizer *iface, HSTRING text, IAsyncOperation_SpeechSynthesisStream **operation ) { - FIXME("iface %p, text %p, operation %p stub.\n", iface, text, operation); + TRACE("iface %p, text %p, operation %p.\n", iface, text, operation); async_operation_inspectable_create(&IID_ISpeechSynthesisStream, NULL, text_to_stream_operation, (IAsyncOperation_IInspectable **)operation); return S_OK; }
static HRESULT CALLBACK ssml_to_stream_operation( IInspectable *invoker, IInspectable **result ) { - return S_OK; + return synthesis_stream_create((ISpeechSynthesisStream **)result); }
static HRESULT WINAPI synthesizer_SynthesizeSsmlToStreamAsync( ISpeechSynthesizer *iface, HSTRING ssml, IAsyncOperation_SpeechSynthesisStream **operation ) { - FIXME("iface %p, text %p, operation %p stub.\n", iface, ssml, operation); + TRACE("iface %p, text %p, operation %p.\n", iface, ssml, operation); async_operation_inspectable_create(&IID_ISpeechSynthesisStream, NULL, ssml_to_stream_operation, (IAsyncOperation_IInspectable **)operation); return S_OK; } diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 4dd1fd7d14c..2db216e07e2 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -939,13 +939,10 @@ static void test_SpeechSynthesizer(void) check_interface(operation_ss_stream, &IID_IAgileObject, TRUE);
hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &ss_stream); - todo_wine ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr); + ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr);
- if (hr == S_OK && ss_stream) - { - ref = ISpeechSynthesisStream_Release(ss_stream); - todo_wine ok(ref == 0, "Got unexpected ref %lu.\n", ref); - } + ref = ISpeechSynthesisStream_Release(ss_stream); + ok(ref == 0, "Got unexpected ref %lu.\n", ref);
IAsyncOperation_SpeechSynthesisStream_Release(operation_ss_stream); WindowsDeleteString(str); @@ -963,13 +960,10 @@ static void test_SpeechSynthesizer(void) check_interface(operation_ss_stream, &IID_IAgileObject, TRUE);
hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &ss_stream); - todo_wine ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr); + ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr);
- if (hr == S_OK && ss_stream) - { - ref = ISpeechSynthesisStream_Release(ss_stream); - ok(ref == 0, "Got unexpected ref %lu.\n", ref); - } + ref = ISpeechSynthesisStream_Release(ss_stream); + ok(ref == 0, "Got unexpected ref %lu.\n", ref);
IAsyncOperation_SpeechSynthesisStream_Release(operation_ss_stream); WindowsDeleteString(str);
Rémi Bernon (@rbernon) commented about dlls/windows.media.speech/tests/speech.c:
compilation_result = (void*)0xdeadbeef; hr = IAsyncOperation_SpeechRecognitionCompilationResult_GetResults(operation, &compilation_result);
if (hr == S_OK) /* Sometimes the operation could have already finished here, */
goto skip_await; /* if so skip waiting and getting the results a second time. */
I'd suggest to simply remove that racy `GetResult` check, but otherwise what about changing the check to `ok(hr == E_ILLEGAL_METHOD_CALL || hr == S_OK, ...)`, and then and putting the rest in an `if (hr == E_ILLEGAL_METHOD_CALL)` block?
Gotos are more often used to skip tests after a todo_wine, so that implementing the call only require to remove the todo_wine and the goto, but for normal control flow I think ifs are better.
Rémi Bernon (@rbernon) commented about dlls/windows.media.speech/synthesizer.c:
return E_NOTIMPL;
}
+static HRESULT CALLBACK text_to_stream_operation( IInspectable *invoker, IInspectable **result ) +{
- return S_OK;
+}
static HRESULT WINAPI synthesizer_SynthesizeTextToStreamAsync( ISpeechSynthesizer *iface, HSTRING text, IAsyncOperation_SpeechSynthesisStream **operation ) { FIXME("iface %p, text %p, operation %p stub.\n", iface, text, operation);
- return E_NOTIMPL;
- async_operation_inspectable_create(&IID_ISpeechSynthesisStream, NULL, text_to_stream_operation, (IAsyncOperation_IInspectable **)operation);
This should probably be `IID_IAsyncOperation_SpeechSynthesisStream` instead?
Rémi Bernon (@rbernon) commented about dlls/windows.media.speech/synthesizer.c:
return S_OK;
}
+static HRESULT CALLBACK ssml_to_stream_operation( IInspectable *invoker, IInspectable **result ) +{
- return S_OK;
+}
static HRESULT WINAPI synthesizer_SynthesizeSsmlToStreamAsync( ISpeechSynthesizer *iface, HSTRING ssml, IAsyncOperation_SpeechSynthesisStream **operation ) { FIXME("iface %p, text %p, operation %p stub.\n", iface, ssml, operation);
- return E_NOTIMPL;
- async_operation_inspectable_create(&IID_ISpeechSynthesisStream, NULL, ssml_to_stream_operation, (IAsyncOperation_IInspectable **)operation);
Here too, `IID_IAsyncOperation_SpeechSynthesisStream` I guess.
On Fri Jun 10 10:25:14 2022 +0000, Rémi Bernon wrote:
I'd suggest to simply remove that racy `GetResult` check, but otherwise what about changing the check to `ok(hr == E_ILLEGAL_METHOD_CALL || hr == S_OK, ...)`, and then and putting the rest in an `if (hr == E_ILLEGAL_METHOD_CALL)` block? Gotos are more often used to skip tests after a todo_wine, so that implementing the call only require to remove the todo_wine and the goto, but for normal control flow I think ifs are better.
Yeah, an if block sounds cleaner. I'd like to keep the check though.
On Fri Jun 10 12:37:58 2022 +0000, Rémi Bernon wrote:
This should probably be `IID_IAsyncOperation_SpeechSynthesisStream` instead?
Good, catch!
Rémi Bernon (@rbernon) commented about dlls/windows.media.speech/synthesizer.c:
+HRESULT WINAPI synthesis_stream_GetRuntimeClassName( ISpeechSynthesisStream *iface, HSTRING *class_name ) +{
- FIXME("iface %p, class_name %p stub.\n", iface, class_name);
- return E_NOTIMPL;
+}
+HRESULT WINAPI synthesis_stream_GetTrustLevel( ISpeechSynthesisStream *iface, TrustLevel *trust_level ) +{
- FIXME("iface %p, trust_level %p stub.\n", iface, trust_level);
- return E_NOTIMPL;
+}
+HRESULT WINAPI synthesis_stream_get_Markers( ISpeechSynthesisStream *iface, IVectorView_IMediaMarker **value ) +{
- FIXME("iface %p, value %p stub!\n", iface, value);
- *value = NULL;
Shouldn't we return an empty vector view instead? Either create the vector on the fly, or more probably better in the stream constructor and return a view to it here?
On Fri Jun 10 12:42:13 2022 +0000, Rémi Bernon wrote:
Shouldn't we return an empty vector view instead? Either create the vector on the fly, or probably better in the stream constructor and return a view to it here?
Yup, that's probably a better idea than this. I think returning NULL is actually not good anyway.