-- v2: windows.media.speech: Return semi-stub IAsyncInfo from async_with_progress_uint32_QueryInterface(). windows.media.speech: Add semi-stub for synthesis_stream_input_ReadAsync(). windows.media.speech: Add stub IInputStream interface to SpeechSynthesisStream class.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.media.speech/private.h | 1 + dlls/windows.media.speech/synthesizer.c | 153 ++++++++++++++++++++++- dlls/windows.media.speech/tests/speech.c | 7 +- 3 files changed, 159 insertions(+), 2 deletions(-)
diff --git a/dlls/windows.media.speech/private.h b/dlls/windows.media.speech/private.h index fb5b936fb01..e7921370f11 100644 --- a/dlls/windows.media.speech/private.h +++ b/dlls/windows.media.speech/private.h @@ -33,6 +33,7 @@
#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections +#define WIDL_using_Windows_Storage_Streams #include "windows.foundation.h" #define WIDL_using_Windows_Globalization #include "windows.globalization.h" diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 80968333c8a..c2bed2e45b9 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -151,10 +151,10 @@ static struct voice_information_vector all_voices = * ISpeechSynthesisStream * */ - struct synthesis_stream { ISpeechSynthesisStream ISpeechSynthesisStream_iface; + IRandomAccessStream IRandomAccessStream_iface; LONG ref;
IVector_IMediaMarker *markers; @@ -180,6 +180,13 @@ HRESULT WINAPI synthesis_stream_QueryInterface( ISpeechSynthesisStream *iface, R return S_OK; }
+ if (IsEqualGUID(iid, &IID_IRandomAccessStream)) + { + IRandomAccessStream_AddRef(&impl->IRandomAccessStream_iface); + *out = &impl->IRandomAccessStream_iface; + return S_OK; + } + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *out = NULL; return E_NOINTERFACE; @@ -246,6 +253,149 @@ static const struct ISpeechSynthesisStreamVtbl synthesis_stream_vtbl = };
+static inline struct synthesis_stream *impl_from_IRandomAccessStream( IRandomAccessStream *iface ) +{ + return CONTAINING_RECORD(iface, struct synthesis_stream, IRandomAccessStream_iface); +} + +static HRESULT WINAPI synthesis_stream_random_access_QueryInterface( IRandomAccessStream *iface, REFIID iid, void **out ) +{ + struct synthesis_stream *impl = impl_from_IRandomAccessStream(iface); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out ); + + return ISpeechSynthesisStream_QueryInterface( &impl->ISpeechSynthesisStream_iface, iid, out ); +} + +static ULONG WINAPI synthesis_stream_random_access_AddRef( IRandomAccessStream *iface ) +{ + struct synthesis_stream *impl = impl_from_IRandomAccessStream(iface); + + TRACE( "iface %p.\n", iface ); + return ISpeechSynthesisStream_AddRef( &impl->ISpeechSynthesisStream_iface ); +} + +static ULONG WINAPI synthesis_stream_random_access_Release( IRandomAccessStream *iface ) +{ + struct synthesis_stream *impl = impl_from_IRandomAccessStream(iface); + + TRACE( "iface %p.\n", iface ); + return ISpeechSynthesisStream_Release( &impl->ISpeechSynthesisStream_iface ); +} + +static HRESULT WINAPI synthesis_stream_random_access_GetIids( IRandomAccessStream *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 synthesis_stream_random_access_GetRuntimeClassName( IRandomAccessStream *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub.\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_GetTrustLevel( IRandomAccessStream *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub.\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_get_Size( IRandomAccessStream *iface, UINT64 *value ) +{ + FIXME( "iface %p, value %p stub.\n", iface, value ); + + *value = 0; + return S_OK; +} + +static HRESULT WINAPI synthesis_stream_random_access_put_Size( IRandomAccessStream *iface, UINT64 value ) +{ + FIXME( "iface %p, value %I64u stub.\n", iface, value ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_GetInputStreamAt( IRandomAccessStream *iface, UINT64 position, + IInputStream **stream ) +{ + FIXME( "iface %p, position %I64u, stream %p stub.\n", iface, position, stream ); + + *stream = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_GetOutputStreamAt( IRandomAccessStream *iface, UINT64 position, + IOutputStream **stream ) +{ + FIXME( "iface %p, position %I64u, stream %p stub.\n", iface, position, stream ); + + *stream = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_get_Position( IRandomAccessStream *iface, UINT64 *value ) +{ + FIXME( "iface %p, value %p stub.\n", iface, value ); + + *value = 0; + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_Seek( IRandomAccessStream *iface, UINT64 position ) +{ + FIXME( "iface %p, position %I64u stub.\n", iface, position ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_CloneStream( IRandomAccessStream *iface, IRandomAccessStream **stream ) +{ + FIXME( "iface %p, stream %p stub.\n", iface, stream ); + + *stream = NULL; + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_get_CanRead( IRandomAccessStream *iface, BOOLEAN *value ) +{ + FIXME( "iface %p, value %p stub.\n", iface, value ); + + *value = FALSE; + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_random_access_get_CanWrite( IRandomAccessStream *iface, BOOLEAN *value ) +{ + FIXME( "iface %p, value %p stub.\n", iface, value ); + + *value = FALSE; + return E_NOTIMPL; +} + +static const struct IRandomAccessStreamVtbl synthesis_stream_random_access_vtbl = +{ + /* IUnknown methods */ + synthesis_stream_random_access_QueryInterface, + synthesis_stream_random_access_AddRef, + synthesis_stream_random_access_Release, + /* IInspectable methods */ + synthesis_stream_random_access_GetIids, + synthesis_stream_random_access_GetRuntimeClassName, + synthesis_stream_random_access_GetTrustLevel, + /* IRandomAccessStream methods */ + synthesis_stream_random_access_get_Size, + synthesis_stream_random_access_put_Size, + synthesis_stream_random_access_GetInputStreamAt, + synthesis_stream_random_access_GetOutputStreamAt, + synthesis_stream_random_access_get_Position, + synthesis_stream_random_access_Seek, + synthesis_stream_random_access_CloneStream, + synthesis_stream_random_access_get_CanRead, + synthesis_stream_random_access_get_CanWrite, +}; + + static HRESULT synthesis_stream_create( ISpeechSynthesisStream **out ) { struct synthesis_stream *impl; @@ -267,6 +417,7 @@ static HRESULT synthesis_stream_create( ISpeechSynthesisStream **out ) }
impl->ISpeechSynthesisStream_iface.lpVtbl = &synthesis_stream_vtbl; + impl->IRandomAccessStream_iface.lpVtbl = &synthesis_stream_random_access_vtbl; impl->ref = 1; if (FAILED(hr = vector_inspectable_create(&markers_iids, (IVector_IInspectable**)&impl->markers))) goto error; diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 422df544d59..719c97a52e2 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -29,6 +29,7 @@
#define WIDL_using_Windows_Foundation #define WIDL_using_Windows_Foundation_Collections +#define WIDL_using_Windows_Storage_Streams #include "windows.foundation.h" #define WIDL_using_Windows_Globalization #include "windows.globalization.h" @@ -36,7 +37,6 @@ #include "windows.media.speechrecognition.h" #define WIDL_using_Windows_Media_SpeechSynthesis #include "windows.media.speechsynthesis.h" - #include "wine/test.h"
#define AsyncStatus_Closed 4 @@ -788,6 +788,7 @@ static void test_SpeechSynthesizer(void) IVectorView_VoiceInformation *voices = NULL; IInstalledVoicesStatic *voices_static = NULL; ISpeechSynthesisStream *ss_stream = NULL, *tmp; + IRandomAccessStream *ra_stream; IVoiceInformation *voice; IInspectable *inspectable = NULL, *tmp_inspectable = NULL; IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; @@ -943,6 +944,10 @@ static void test_SpeechSynthesizer(void) hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &ss_stream); ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr);
+ hr = ISpeechSynthesisStream_QueryInterface(ss_stream, &IID_IRandomAccessStream, (void **)&ra_stream); + ok(hr == S_OK, "QueryInteface(&IID_IRandomAccessStream) failed, hr %#lx\n", hr); + IRandomAccessStream_Release(ra_stream); + tmp = (void *)0xdeadbeef; hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &tmp); ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.media.speech/synthesizer.c | 79 ++++++++++++++++++++++++ dlls/windows.media.speech/tests/speech.c | 9 +++ 2 files changed, 88 insertions(+)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index c2bed2e45b9..206b4007943 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -155,6 +155,7 @@ struct synthesis_stream { ISpeechSynthesisStream ISpeechSynthesisStream_iface; IRandomAccessStream IRandomAccessStream_iface; + IInputStream IInputStream_iface; LONG ref;
IVector_IMediaMarker *markers; @@ -187,6 +188,13 @@ HRESULT WINAPI synthesis_stream_QueryInterface( ISpeechSynthesisStream *iface, R return S_OK; }
+ if (IsEqualGUID(iid, &IID_IInputStream)) + { + IInputStream_AddRef(&impl->IInputStream_iface); + *out = &impl->IInputStream_iface; + return S_OK; + } + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); *out = NULL; return E_NOINTERFACE; @@ -396,6 +404,76 @@ static const struct IRandomAccessStreamVtbl synthesis_stream_random_access_vtbl };
+static inline struct synthesis_stream *impl_from_IInputStream( IInputStream *iface ) +{ + return CONTAINING_RECORD(iface, struct synthesis_stream, IInputStream_iface); +} + +static HRESULT WINAPI synthesis_stream_input_QueryInterface( IInputStream *iface, REFIID iid, void **out ) +{ + struct synthesis_stream *impl = impl_from_IInputStream(iface); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out ); + + return ISpeechSynthesisStream_QueryInterface( &impl->ISpeechSynthesisStream_iface, iid, out ); +} + +static ULONG WINAPI synthesis_stream_input_AddRef( IInputStream *iface ) +{ + struct synthesis_stream *impl = impl_from_IInputStream(iface); + + TRACE( "iface %p.\n", iface ); + return ISpeechSynthesisStream_AddRef( &impl->ISpeechSynthesisStream_iface ); +} + +static ULONG WINAPI synthesis_stream_input_Release( IInputStream *iface ) +{ + struct synthesis_stream *impl = impl_from_IInputStream(iface); + + TRACE( "iface %p.\n", iface ); + return ISpeechSynthesisStream_Release( &impl->ISpeechSynthesisStream_iface ); +} + +static HRESULT WINAPI synthesis_stream_input_GetIids( IInputStream *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 synthesis_stream_input_GetRuntimeClassName( IInputStream *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub.\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_input_GetTrustLevel( IInputStream *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub.\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI synthesis_stream_input_ReadAsync( IInputStream *iface, IBuffer *buffer, UINT32 count, + InputStreamOptions options, IAsyncOperationWithProgress_IBuffer_UINT32 **operation) +{ + FIXME( "iface %p, buffer %p, count %u, options %d, operation %p stub.\n", iface, buffer, count, options, operation ); + return E_NOTIMPL; +} + +static const struct IInputStreamVtbl synthesis_stream_input_vtbl = +{ + /* IUnknown methods */ + synthesis_stream_input_QueryInterface, + synthesis_stream_input_AddRef, + synthesis_stream_input_Release, + /* IInspectable methods */ + synthesis_stream_input_GetIids, + synthesis_stream_input_GetRuntimeClassName, + synthesis_stream_input_GetTrustLevel, + /* IInputStream methods */ + synthesis_stream_input_ReadAsync +}; + + static HRESULT synthesis_stream_create( ISpeechSynthesisStream **out ) { struct synthesis_stream *impl; @@ -418,6 +496,7 @@ static HRESULT synthesis_stream_create( ISpeechSynthesisStream **out )
impl->ISpeechSynthesisStream_iface.lpVtbl = &synthesis_stream_vtbl; impl->IRandomAccessStream_iface.lpVtbl = &synthesis_stream_random_access_vtbl; + impl->IInputStream_iface.lpVtbl = &synthesis_stream_input_vtbl; impl->ref = 1; if (FAILED(hr = vector_inspectable_create(&markers_iids, (IVector_IInspectable**)&impl->markers))) goto error; diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 719c97a52e2..16e80dee036 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -789,6 +789,7 @@ static void test_SpeechSynthesizer(void) IInstalledVoicesStatic *voices_static = NULL; ISpeechSynthesisStream *ss_stream = NULL, *tmp; IRandomAccessStream *ra_stream; + IInputStream *inp_stream; IVoiceInformation *voice; IInspectable *inspectable = NULL, *tmp_inspectable = NULL; IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; @@ -798,6 +799,7 @@ static void test_SpeechSynthesizer(void) struct async_inspectable_handler async_inspectable_handler; HMODULE hdll; HSTRING str, str2; + UINT64 value; HRESULT hr; UINT32 size; ULONG ref; @@ -946,8 +948,15 @@ static void test_SpeechSynthesizer(void)
hr = ISpeechSynthesisStream_QueryInterface(ss_stream, &IID_IRandomAccessStream, (void **)&ra_stream); ok(hr == S_OK, "QueryInteface(&IID_IRandomAccessStream) failed, hr %#lx\n", hr); + hr = IRandomAccessStream_get_Size(ra_stream, &value); + ok(hr == S_OK, "_get_Size failed, hr %#lx\n", hr); + todo_wine ok(value, "got 0.\n"); IRandomAccessStream_Release(ra_stream);
+ hr = ISpeechSynthesisStream_QueryInterface(ss_stream, &IID_IInputStream, (void **)&inp_stream); + ok(hr == S_OK, "QueryInteface(&IID_IRandomAccessStream) failed, hr %#lx\n", hr); + IInputStream_Release(inp_stream); + tmp = (void *)0xdeadbeef; hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &tmp); ok(hr == S_OK, "IAsyncOperation_SpeechSynthesisStream_GetResults failed, hr %#lx\n", hr);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.media.speech/synthesizer.c | 167 ++++++++++++++++++++++- dlls/windows.media.speech/tests/speech.c | 27 ++++ 2 files changed, 193 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 206b4007943..75e05f15aeb 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -404,6 +404,171 @@ static const struct IRandomAccessStreamVtbl synthesis_stream_random_access_vtbl };
+struct synthesis_stream_async_operation +{ + IAsyncOperationWithProgress_IBuffer_UINT32 ISynthesisSteamBufferAsync_iface; + IBuffer *buffer; + IInputStream *inp_stream; + + LONG ref; +}; + +static inline struct synthesis_stream_async_operation *impl_from_ISynthesisSteamBufferAsync( IAsyncOperationWithProgress_IBuffer_UINT32 *iface ) +{ + return CONTAINING_RECORD( iface, struct synthesis_stream_async_operation, ISynthesisSteamBufferAsync_iface ); +} + +static HRESULT WINAPI async_with_progress_uint32_QueryInterface( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, REFIID iid, void **out ) +{ + struct synthesis_stream_async_operation *impl = impl_from_ISynthesisSteamBufferAsync( 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_IAgileObject ) || + IsEqualGUID( iid, &IID_IAsyncOperationWithProgress_IBuffer_UINT32 )) + { + *out = &impl->ISynthesisSteamBufferAsync_iface; + IAsyncOperationWithProgress_IBuffer_UINT32_AddRef( &impl->ISynthesisSteamBufferAsync_iface ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid) ); + return E_NOINTERFACE; +} + +static ULONG WINAPI async_with_progress_uint32_AddRef( IAsyncOperationWithProgress_IBuffer_UINT32 *iface ) +{ + struct synthesis_stream_async_operation *impl = impl_from_ISynthesisSteamBufferAsync( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI async_with_progress_uint32_Release( IAsyncOperationWithProgress_IBuffer_UINT32 *iface ) +{ + struct synthesis_stream_async_operation *impl = impl_from_ISynthesisSteamBufferAsync( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) + { + /* guard against re-entry if inner releases an outer iface */ + IBuffer_Release( impl->buffer ); + IInputStream_Release( impl->inp_stream ); + free( impl ); + } + + return ref; +} + +static HRESULT WINAPI async_with_progress_uint32_GetIids( IAsyncOperationWithProgress_IBuffer_UINT32 *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 async_with_progress_uint32_GetRuntimeClassName( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub.\n", iface, class_name ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI async_with_progress_uint32_GetTrustLevel( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI async_with_progress_uint32_put_Progress( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, + IAsyncOperationProgressHandler_IBuffer_UINT32 *handler ) +{ + FIXME( "iface %p, handler %p stub.\n", iface, handler ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI async_with_progress_uint32_get_Progress( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, + IAsyncOperationProgressHandler_IBuffer_UINT32 **handler ) +{ + FIXME( "iface %p, handler %p stub.\n", iface, handler ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI async_with_progress_uint32_put_Completed( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, + IAsyncOperationWithProgressCompletedHandler_IBuffer_UINT32 *handler ) +{ + FIXME( "iface %p, handler %p stub.\n", iface, handler ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI async_with_progress_uint32_get_Completed( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, + IAsyncOperationWithProgressCompletedHandler_IBuffer_UINT32 **handler ) +{ + FIXME( "iface %p, handler %p stub.\n", iface, handler ); + + return E_NOTIMPL; +} + +static HRESULT WINAPI async_with_progress_uint32_GetResults( IAsyncOperationWithProgress_IBuffer_UINT32 *iface, + IBuffer **results ) +{ + struct synthesis_stream_async_operation *impl = impl_from_ISynthesisSteamBufferAsync( iface ); + + TRACE( "iface %p, results %p.\n", iface, results ); + + IBuffer_AddRef( impl->buffer ); + *results = impl->buffer; + return S_OK; +} + +IAsyncOperationWithProgress_IBuffer_UINT32Vtbl async_with_progress_uint32_vtbl = +{ + /* IUnknown methods */ + async_with_progress_uint32_QueryInterface, + async_with_progress_uint32_AddRef, + async_with_progress_uint32_Release, + /* IInspectable methods */ + async_with_progress_uint32_GetIids, + async_with_progress_uint32_GetRuntimeClassName, + async_with_progress_uint32_GetTrustLevel, + /* IAsyncOperationWithProgress<Windows.Storage.Streams.IBuffer *,UINT32> */ + async_with_progress_uint32_put_Progress, + async_with_progress_uint32_get_Progress, + async_with_progress_uint32_put_Completed, + async_with_progress_uint32_get_Completed, + async_with_progress_uint32_GetResults, +}; + +static HRESULT async_operation_with_progress_buffer_uint32_create( IInputStream *inp_stream, + IBuffer *buffer, + IAsyncOperationWithProgress_IBuffer_UINT32 **out) +{ + struct synthesis_stream_async_operation *impl; + + if (!inp_stream || !buffer || !out) return E_POINTER; + + *out = NULL; + if (!(impl = calloc(1, sizeof(*impl)))) + return E_OUTOFMEMORY; + + impl->ref = 1; + IBuffer_AddRef( buffer ); + impl->buffer = buffer; + IInputStream_AddRef( inp_stream ); + impl->inp_stream = inp_stream; + impl->ISynthesisSteamBufferAsync_iface.lpVtbl = &async_with_progress_uint32_vtbl; + *out = &impl->ISynthesisSteamBufferAsync_iface; + return S_OK; +} + + static inline struct synthesis_stream *impl_from_IInputStream( IInputStream *iface ) { return CONTAINING_RECORD(iface, struct synthesis_stream, IInputStream_iface); @@ -456,7 +621,7 @@ static HRESULT WINAPI synthesis_stream_input_ReadAsync( IInputStream *iface, IBu InputStreamOptions options, IAsyncOperationWithProgress_IBuffer_UINT32 **operation) { FIXME( "iface %p, buffer %p, count %u, options %d, operation %p stub.\n", iface, buffer, count, options, operation ); - return E_NOTIMPL; + return async_operation_with_progress_buffer_uint32_create( iface, buffer, operation ); }
static const struct IInputStreamVtbl synthesis_stream_input_vtbl = diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index 16e80dee036..f652a0c832c 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -782,14 +782,18 @@ static void test_SpeechSynthesizer(void) 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"; + static const WCHAR *buffer_class_name = L"Windows.Storage.Streams.Buffer"; IActivationFactory *factory = NULL, *factory2 = NULL; + IBufferFactory *buffer_factory = NULL; IAsyncOperation_SpeechSynthesisStream *operation_ss_stream = NULL; + IAsyncOperationWithProgress_IBuffer_UINT32 *operation_read_async = NULL; IVectorView_IMediaMarker *media_markers = NULL; IVectorView_VoiceInformation *voices = NULL; IInstalledVoicesStatic *voices_static = NULL; ISpeechSynthesisStream *ss_stream = NULL, *tmp; IRandomAccessStream *ra_stream; IInputStream *inp_stream; + IBuffer *buffer = NULL, *buffer2 = NULL; IVoiceInformation *voice; IInspectable *inspectable = NULL, *tmp_inspectable = NULL; IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; @@ -953,9 +957,32 @@ static void test_SpeechSynthesizer(void) todo_wine ok(value, "got 0.\n"); IRandomAccessStream_Release(ra_stream);
+ hr = WindowsCreateString(buffer_class_name, wcslen(buffer_class_name), &str2); + ok(hr == S_OK, "WindowsCreateString failed, hr %#lx.\n", hr); + hr = RoGetActivationFactory(str2, &IID_IActivationFactory, (void **)&factory2); + ok(hr == S_OK, "RoGetActivationFactory failed, hr %#lx.\n", hr); + WindowsDeleteString(str2); + + hr = IActivationFactory_QueryInterface(factory2, &IID_IBufferFactory, (void **)&buffer_factory); + ok(hr == S_OK, "QueryInterface IID_IBufferFactory failed, hr %#lx.\n", hr); + IActivationFactory_Release(factory2); + hr = IBufferFactory_Create(buffer_factory, value, &buffer); + ok(hr == S_OK, "IBufferFactory_Create failed, hr %#lx.\n", hr); + IBufferFactory_Release(buffer_factory); + hr = ISpeechSynthesisStream_QueryInterface(ss_stream, &IID_IInputStream, (void **)&inp_stream); ok(hr == S_OK, "QueryInteface(&IID_IRandomAccessStream) failed, hr %#lx\n", hr); + hr = IInputStream_ReadAsync(inp_stream, buffer, value, InputStreamOptions_ReadAhead, &operation_read_async); + ok(hr == S_OK, "_ReadAsync failed, hr %#lx\n", hr); IInputStream_Release(inp_stream); + IAsyncOperationWithProgress_IBuffer_UINT32_GetResults(operation_read_async, &buffer2); + ok(hr == S_OK, "_GetResults failed, hr %#lx\n", hr); + ok(buffer2 == buffer, "got %p, %p.\n", buffer, buffer2); + IBuffer_Release(buffer); + ref = IAsyncOperationWithProgress_IBuffer_UINT32_Release(operation_read_async); + ok(!ref, "got refcount %ld.\n", ref); + ref = IBuffer_Release(buffer2); + ok(!ref, "got refcount %ld.\n", ref);
tmp = (void *)0xdeadbeef; hr = IAsyncOperation_SpeechSynthesisStream_GetResults(operation_ss_stream, &tmp);
From: Paul Gofman pgofman@codeweavers.com
--- dlls/windows.media.speech/synthesizer.c | 68 ++++++++++++++++++++++++ dlls/windows.media.speech/tests/speech.c | 1 + 2 files changed, 69 insertions(+)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 75e05f15aeb..67f028dc52f 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -407,6 +407,7 @@ static const struct IRandomAccessStreamVtbl synthesis_stream_random_access_vtbl struct synthesis_stream_async_operation { IAsyncOperationWithProgress_IBuffer_UINT32 ISynthesisSteamBufferAsync_iface; + IAsyncInfo IAsyncInfo_iface; IBuffer *buffer; IInputStream *inp_stream;
@@ -434,6 +435,13 @@ static HRESULT WINAPI async_with_progress_uint32_QueryInterface( IAsyncOperation return S_OK; }
+ if (IsEqualGUID( iid, &IID_IAsyncInfo )) + { + *out = &impl->IAsyncInfo_iface; + IAsyncInfo_AddRef( &impl->IAsyncInfo_iface ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid) ); return E_NOINTERFACE; } @@ -546,6 +554,65 @@ IAsyncOperationWithProgress_IBuffer_UINT32Vtbl async_with_progress_uint32_vtbl = async_with_progress_uint32_GetResults, };
+DEFINE_IINSPECTABLE(async_info, IAsyncInfo, struct synthesis_stream_async_operation, ISynthesisSteamBufferAsync_iface) + +static HRESULT WINAPI async_info_get_Id( IAsyncInfo *iface, UINT32 *id ) +{ + TRACE( "iface %p, id %p.\n", iface, id ); + + *id = 1; + return S_OK; +} + +static HRESULT WINAPI async_info_get_Status( IAsyncInfo *iface, AsyncStatus *status ) +{ + TRACE( "iface %p, status %p.\n", iface, status ); + + *status = Completed; + return S_OK; +} + +static HRESULT WINAPI async_info_get_ErrorCode( IAsyncInfo *iface, HRESULT *error_code ) +{ + FIXME( "iface %p, error_code %p.\n", iface, error_code ); + + *error_code = S_OK; + return S_OK; +} + +static HRESULT WINAPI async_info_Cancel( IAsyncInfo *iface ) +{ + FIXME( "iface %p.\n", iface ); + + return S_OK; +} + +static HRESULT WINAPI async_info_Close( IAsyncInfo *iface ) +{ + FIXME( "iface %p.\n", iface ); + + return S_OK; +} + + +static const struct IAsyncInfoVtbl async_info_vtbl = +{ + /* IUnknown methods */ + async_info_QueryInterface, + async_info_AddRef, + async_info_Release, + /* IInspectable methods */ + async_info_GetIids, + async_info_GetRuntimeClassName, + async_info_GetTrustLevel, + /* IAsyncInfo */ + async_info_get_Id, + async_info_get_Status, + async_info_get_ErrorCode, + async_info_Cancel, + async_info_Close, +}; + static HRESULT async_operation_with_progress_buffer_uint32_create( IInputStream *inp_stream, IBuffer *buffer, IAsyncOperationWithProgress_IBuffer_UINT32 **out) @@ -564,6 +631,7 @@ static HRESULT async_operation_with_progress_buffer_uint32_create( IInputStream IInputStream_AddRef( inp_stream ); impl->inp_stream = inp_stream; impl->ISynthesisSteamBufferAsync_iface.lpVtbl = &async_with_progress_uint32_vtbl; + impl->IAsyncInfo_iface.lpVtbl = &async_info_vtbl; *out = &impl->ISynthesisSteamBufferAsync_iface; return S_OK; } diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index f652a0c832c..b1362678212 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -975,6 +975,7 @@ static void test_SpeechSynthesizer(void) hr = IInputStream_ReadAsync(inp_stream, buffer, value, InputStreamOptions_ReadAhead, &operation_read_async); ok(hr == S_OK, "_ReadAsync failed, hr %#lx\n", hr); IInputStream_Release(inp_stream); + check_async_info((IInspectable *)operation_read_async, 1, Completed, S_OK); IAsyncOperationWithProgress_IBuffer_UINT32_GetResults(operation_read_async, &buffer2); ok(hr == S_OK, "_GetResults failed, hr %#lx\n", hr); ok(buffer2 == buffer, "got %p, %p.\n", buffer, buffer2);
This merge request was approved by Bernhard Kölbl.