A recent update for Microsoft Flight Simulator requires this.
Signed-off-by: Andrew Eikum aeikum@codeweavers.com --- dlls/windows.media.speech/synthesizer.c | 33 +++++++++++++++++++++++ dlls/windows.media.speech/tests/speech.c | 12 +++++++++ include/windows.media.speechsynthesis.idl | 32 ++++++++++++++++++++++ 3 files changed, 77 insertions(+)
diff --git a/dlls/windows.media.speech/synthesizer.c b/dlls/windows.media.speech/synthesizer.c index 3863e468d36..179229b4bb4 100644 --- a/dlls/windows.media.speech/synthesizer.c +++ b/dlls/windows.media.speech/synthesizer.c @@ -151,6 +151,7 @@ static struct voice_information_vector all_voices = struct speech_synthesizer { ISpeechSynthesizer ISpeechSynthesizer_iface; + ISpeechSynthesizer2 ISpeechSynthesizer2_iface; IClosable IClosable_iface; LONG ref; }; @@ -181,6 +182,13 @@ static HRESULT STDMETHODCALLTYPE speech_synthesizer_QueryInterface( return S_OK; }
+ if (IsEqualGUID(iid, &IID_ISpeechSynthesizer2)) + { + IUnknown_AddRef(iface); + *out = &impl->ISpeechSynthesizer2_iface; + return S_OK; + } + if (IsEqualGUID(iid, &IID_IClosable)) { IUnknown_AddRef(iface); @@ -289,6 +297,30 @@ static const struct ISpeechSynthesizerVtbl speech_synthesizer_vtbl = speech_synthesizer_get_Voice, };
+ +DEFINE_IINSPECTABLE(speech_synthesizer2, ISpeechSynthesizer2, struct speech_synthesizer, ISpeechSynthesizer_iface) + +static HRESULT STDMETHODCALLTYPE speech_synthesizer2_get_Options(ISpeechSynthesizer2 *iface, ISpeechSynthesizerOptions **value) +{ + FIXME("iface %p, value %p stub.\n", iface, value); + + return E_NOTIMPL; +} + +static const struct ISpeechSynthesizer2Vtbl speech_synthesizer2_vtbl = +{ + /* IUnknown methods */ + speech_synthesizer2_QueryInterface, + speech_synthesizer2_AddRef, + speech_synthesizer2_Release, + /* IInspectable methods */ + speech_synthesizer2_GetIids, + speech_synthesizer2_GetRuntimeClassName, + speech_synthesizer2_GetTrustLevel, + /* ISpeechSynthesizer2 methods */ + speech_synthesizer2_get_Options, +}; + static HRESULT STDMETHODCALLTYPE closable_QueryInterface( IClosable *iface, REFIID iid, void **out) { @@ -467,6 +499,7 @@ static HRESULT STDMETHODCALLTYPE factory_ActivateInstance( }
obj->ISpeechSynthesizer_iface.lpVtbl = &speech_synthesizer_vtbl; + obj->ISpeechSynthesizer2_iface.lpVtbl = &speech_synthesizer2_vtbl; obj->IClosable_iface.lpVtbl = &closable_vtbl; obj->ref = 1; *instance = (IInspectable *)&obj->ISpeechSynthesizer_iface; diff --git a/dlls/windows.media.speech/tests/speech.c b/dlls/windows.media.speech/tests/speech.c index fc0a8d762c1..e88cfc25d54 100644 --- a/dlls/windows.media.speech/tests/speech.c +++ b/dlls/windows.media.speech/tests/speech.c @@ -557,6 +557,7 @@ static void test_SpeechSynthesizer(void) IInspectable *inspectable = NULL, *tmp_inspectable = NULL; IAgileObject *agile_object = NULL, *tmp_agile_object = NULL; ISpeechSynthesizer *synthesizer; + ISpeechSynthesizer2 *synthesizer2; IClosable *closable; HMODULE hdll; HSTRING str, str2; @@ -673,6 +674,17 @@ static void test_SpeechSynthesizer(void) 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); + + if (hr == S_OK) + { + ref = ISpeechSynthesizer2_Release(synthesizer2); + ok(ref == 3, "Got unexpected ref %lu.\n", ref); + } + ref = IClosable_Release(closable); ok(ref == 2, "Got unexpected ref %lu.\n", ref);
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl index 29dca510dee..b2c86f37137 100644 --- a/include/windows.media.speechsynthesis.idl +++ b/include/windows.media.speechsynthesis.idl @@ -39,6 +39,7 @@ namespace Windows { interface ISpeechSynthesisStream; runtimeclass SpeechSynthesizer; runtimeclass VoiceInformation; + runtimeclass SpeechSynthesizerOptions; runtimeclass SpeechSynthesisStream; } } @@ -112,6 +113,16 @@ namespace Windows { [propget] HRESULT Voice([out] [retval] VoiceInformation **value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizer), + uuid(a7c5ecb2-4339-4d6a-bbf8-c7a4f1544c2e) + ] + interface ISpeechSynthesizer2 : IInspectable + { + [propget] HRESULT Options([out, retval] SpeechSynthesizerOptions **value); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), exclusiveto(Windows.Media.SpeechSynthesis.VoiceInformation), @@ -126,6 +137,19 @@ namespace Windows { [propget] HRESULT Gender([out] [retval] VoiceGender* value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizerOptions), + uuid(a0e23871-cc3d-43c9-91b1-ee185324d83d) + ] + interface ISpeechSynthesizerOptions : IInspectable + { + [propget] HRESULT IncludeWordBoundaryMetadata([out, retval] boolean *value); + [propput] HRESULT IncludeWordBoundaryMetadata([in] boolean value); + [propget] HRESULT IncludeSentenceBoundaryMetadata([out, retval] boolean *value); + [propput] HRESULT IncludeSentenceBoundaryMetadata([in] boolean value); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), exclusiveto(Windows.Media.SpeechSynthesis.SpeechSynthesizer), @@ -146,6 +170,14 @@ namespace Windows { [default] interface Windows.Media.SpeechSynthesis.IVoiceInformation; }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile) + ] + runtimeclass SpeechSynthesizerOptions + { + [default] interface Windows.Media.SpeechSynthesis.ISpeechSynthesizerOptions; + }
[contract(Windows.Foundation.UniversalApiContract, 1.0)] [marshaling_behavior(agile)]