A recent update for Microsoft Flight Simulator requires this.
Signed-off-by: Andrew Eikum <aeikum(a)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)]
--
2.35.1