[PATCH v6 9/9] windows.media.speech: Add stub ISpeechSynthesisStream iface.

Bernhard Kölbl wine at gitlab.winehq.org
Tue Jun 14 15:52:28 CDT 2022


From: Bernhard Kölbl <besentv at gmail.com>

Based on a patch by Connor McAdams <cmcadams at codeweavers.com>

Silences a warning about narrator being broken in Forza Horizon 5.

Signed-off-by: Bernhard Kölbl <besentv at gmail.com>
---
 dlls/windows.media.speech/synthesizer.c  | 142 ++++++++++++++++++++++-
 dlls/windows.media.speech/tests/speech.c |  37 +++---
 2 files changed, 153 insertions(+), 26 deletions(-)

diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c
index 7e1d19cb4c1..ce257c7c355 100644
--- a/dlls/windows.media.speech/synthesizer.c
+++ b/dlls/windows.media.speech/synthesizer.c
@@ -146,6 +146,140 @@ static struct voice_information_vector all_voices =
     0
 };
 
+/*
+ *
+ * ISpeechSynthesisStream
+ *
+ */
+
+struct synthesis_stream
+{
+    ISpeechSynthesisStream ISpeechSynthesisStream_iface;
+    LONG ref;
+
+    IVector_IMediaMarker *markers;
+};
+
+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 )
+{
+    struct synthesis_stream *impl = impl_from_ISpeechSynthesisStream(iface);
+    FIXME("iface %p, value %p stub!\n", iface, value);
+    return IVector_IMediaMarker_GetView(impl->markers, value);
+}
+
+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;
+    struct vector_iids markers_iids =
+    {
+        .iterable = &IID_IIterable_IMediaMarker,
+        .iterator = &IID_IIterator_IMediaMarker,
+        .vector = &IID_IVector_IMediaMarker,
+        .view = &IID_IVectorView_IMediaMarker,
+    };
+    HRESULT hr;
+
+    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;
+    if (FAILED(hr = vector_inspectable_create(&markers_iids, (IVector_IInspectable**)&impl->markers)))
+        goto error;
+
+    TRACE("created ISpeechSynthesisStream %p.\n", impl);
+    *out = &impl->ISpeechSynthesisStream_iface;
+    return S_OK;
+
+error:
+    free(impl);
+    return hr;
+}
+
 /*
  *
  * SpeechSynthesizer runtimeclass
@@ -243,26 +377,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);
     return async_operation_inspectable_create(&IID_IAsyncOperation_SpeechSynthesisStream, NULL,
                                               text_to_stream_operation, (IAsyncOperation_IInspectable **)operation);
 }
 
 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, ssml %p, operation %p.\n", iface, ssml, operation);
     return async_operation_inspectable_create(&IID_IAsyncOperation_SpeechSynthesisStream, NULL,
                                               ssml_to_stream_operation, (IAsyncOperation_IInspectable **)operation);
 }
diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c
index bea3c5104b1..0d67c8b7cdb 100644
--- a/dlls/windows.media.speech/tests/speech.c
+++ b/dlls/windows.media.speech/tests/speech.c
@@ -947,22 +947,19 @@ 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)
-    {
-        hr = ISpeechSynthesisStream_get_Markers(ss_stream, &media_markers);
-        todo_wine ok(hr == S_OK, "ISpeechSynthesisStream_get_Markers failed, hr %#lx\n", hr);
-        check_interface(media_markers, &IID_IVectorView_IMediaMarker, TRUE);
-        check_interface(media_markers, &IID_IIterable_IMediaMarker, TRUE);
-        check_interface(media_markers, &IID_IAgileObject, TRUE);
+    hr = ISpeechSynthesisStream_get_Markers(ss_stream, &media_markers);
+    ok(hr == S_OK, "ISpeechSynthesisStream_get_Markers failed, hr %#lx\n", hr);
+    check_interface(media_markers, &IID_IVectorView_IMediaMarker, TRUE);
+    check_interface(media_markers, &IID_IIterable_IMediaMarker, TRUE);
+    check_interface(media_markers, &IID_IAgileObject, TRUE);
 
-        ref = IVectorView_IMediaMarker_Release(media_markers);
-        todo_wine ok(ref == 0, "Got unexpected ref %lu.\n", ref);
+    ref = IVectorView_IMediaMarker_Release(media_markers);
+    ok(ref == 0, "Got unexpected ref %lu.\n", ref);
 
-        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);
 
@@ -981,16 +978,12 @@ 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);
+    check_interface(ss_stream, &IID_ISpeechSynthesisStream, TRUE);
+    check_interface(ss_stream, &IID_IAgileObject, TRUE);
 
-    if (hr == S_OK)
-    {
-        check_interface(ss_stream, &IID_ISpeechSynthesisStream, TRUE);
-        check_interface(ss_stream, &IID_IAgileObject, TRUE);
-
-        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);
 
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/217



More information about the wine-devel mailing list