[375638] Add support for Microsoft Speech Platform
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/.classpath b/plugins/org.eclipse.actf.ai.tts.msp/.classpath
new file mode 100644
index 0000000..304e861
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/.cvsignore b/plugins/org.eclipse.actf.ai.tts.msp/.cvsignore
new file mode 100644
index 0000000..ddb0a2d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/.cvsignore
@@ -0,0 +1,2 @@
+bin
+.settings
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/.project b/plugins/org.eclipse.actf.ai.tts.msp/.project
new file mode 100644
index 0000000..7eaa664
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.actf.ai.tts.msp</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/META-INF/MANIFEST.MF b/plugins/org.eclipse.actf.ai.tts.msp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..244dcfc
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/META-INF/MANIFEST.MF
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: ACTF MSP Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.actf.ai.tts.msp;singleton:=true
+Bundle-Version: 0.9.2.qualifier
+Bundle-Activator: org.eclipse.actf.ai.tts.msp.MspPlugin
+Bundle-Vendor: Eclipse.org
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.actf.util.win32,
+ org.eclipse.actf.ai.voice
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/about.html b/plugins/org.eclipse.actf.ai.tts.msp/about.html
new file mode 100644
index 0000000..481dbcf
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/about.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+<p>The Eclipse Foundation makes available all content in this plug-in ("Content").
+Unless otherwise indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available
+at <a href="http://www.eclipse.org/org/documents/epl-v10.php">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, "Program" will mean the Content.</p>
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party ("Redistributor") and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor’s license
+that was provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/build.properties b/plugins/org.eclipse.actf.ai.tts.msp/build.properties
new file mode 100644
index 0000000..661c95d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/build.properties
@@ -0,0 +1,19 @@
+###############################################################################
+# Copyright (c) 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ about.html,\
+ .,\
+ plugin.xml,\
+ plugin.properties,\
+ plugin_zh.properties,\
+ plugin_ja.properties
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/plugin.properties b/plugins/org.eclipse.actf.ai.tts.msp/plugin.properties
new file mode 100644
index 0000000..12bcbe8
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2007, 2012 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+PreferencePage.name=MSP Settings
+voice.exclude=AcTF On-Screen TTS
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/plugin.xml b/plugins/org.eclipse.actf.ai.tts.msp/plugin.xml
new file mode 100644
index 0000000..535465d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/plugin.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension
+ point="org.eclipse.actf.ai.voice.TTSEngine">
+ <engine
+ class="org.eclipse.actf.ai.tts.msp.engine.MspVoice"
+ id="org.eclipse.actf.ai.tts.msp.engine.MspVoice"
+ name="MSP TTS"
+ priority="95"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="org.eclipse.actf.ai.voice.preferences.VoicePreferencePage"
+ class="org.eclipse.actf.ai.tts.msp.preferences.MspPreferencePage"
+ id="org.eclipse.actf.ai.tts.sapi.preferences.SapiPreferencePage"
+ name="%PreferencePage.name"/>
+ </extension>
+
+ <extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer class="org.eclipse.actf.ai.tts.msp.preferences.MspPreferenceInitializer"/>
+ </extension>
+
+</plugin>
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/plugin_ja.properties b/plugins/org.eclipse.actf.ai.tts.msp/plugin_ja.properties
new file mode 100644
index 0000000..2e0f0e1
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/plugin_ja.properties
@@ -0,0 +1,11 @@
+###############################################################################
+# Copyright (c) 2007, 2012 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+PreferencePage.name=MSP\u8a2d\u5b9a
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/plugin_zh.properties b/plugins/org.eclipse.actf.ai.tts.msp/plugin_zh.properties
new file mode 100644
index 0000000..cf8c8a5
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/plugin_zh.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2010, 2012 Shaojian Zhu, IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Shaojian Zhu - initial API and implementation
+# IBM Corporation - initial API and implementation
+###############################################################################
+PreferencePage.name=MSP\u8bbe\u7f6e
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/messages.properties b/plugins/org.eclipse.actf.ai.tts.msp/src/messages.properties
new file mode 100644
index 0000000..1999543
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/messages.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+tts_msp_description=Microsoft Speech Platform TTS Settings
+tts_msp_voicename=&Voice name:
+tts_msp_audiooutput=&Audio Output Device:
+tts_msp_notAvailable=Microsoft Speech Platform TTS is not Available
+tts_msp_test=&Test
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/messages_ja.properties b/plugins/org.eclipse.actf.ai.tts.msp/src/messages_ja.properties
new file mode 100644
index 0000000..d63039c
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/messages_ja.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# Copyright (c) 2007, 2012 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+tts_msp_description=Microsoft Speech Platform TTS\u8a2d\u5b9a
+tts_msp_voicename=\u97f3\u58f0(&V):
+tts_msp_audiooutput=\u30aa\u30fc\u30c7\u30a3\u30aa\u518d\u751f\u30c7\u30d0\u30a4\u30b9(&A):
+tts_msp_notAvailable=Microsoft Speech Platform TTS \u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
+tts_msp_test=\u30c6\u30b9\u30c8(&T)
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/messages_zh.properties b/plugins/org.eclipse.actf.ai.tts.msp/src/messages_zh.properties
new file mode 100644
index 0000000..b51a92e
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/messages_zh.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# Copyright (c) 2010, 2012 Shaojian Zhu, IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Shaojian Zhu - initial API and implementation
+# IBM Corporation - initial API and implementation
+###############################################################################
+tts_msp_description=Microsoft Speech Platform TTS \u8bbe\u7f6e
+tts_msp_voicename=\u4eba\u58f0(&V):
+tts_msp_audiooutput=\u97f3\u9891\u8f93\u51fa\u8bbe\u5907(&A):
+tts_msp_notAvailable=Microsoft Speech Platform TTS \u4e0d\u53ef\u7528
+tts_msp_test=\u6d4b\u8bd5(&T):
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/Messages.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/Messages.java
new file mode 100644
index 0000000..6cdad62
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/Messages.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp;
+
+import org.eclipse.osgi.util.NLS;
+
+public final class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "messages";//$NON-NLS-1$
+
+ private Messages() {
+ // Do not instantiate
+ }
+
+ public static String tts_msp_description;
+ public static String tts_msp_voicename;
+ public static String tts_msp_audiooutput;
+ public static String tts_msp_notAvailable;
+ public static String tts_msp_test;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+}
\ No newline at end of file
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/MspPlugin.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/MspPlugin.java
new file mode 100644
index 0000000..8c9c817
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/MspPlugin.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp;
+
+import org.eclipse.actf.ai.tts.AbstractUIPluginForTTS;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The main plugin class to be used in the desktop.
+ */
+public class MspPlugin extends AbstractUIPluginForTTS {
+
+ // The shared instance.
+ private static MspPlugin plugin;
+
+ /**
+ * The constructor.
+ */
+ public MspPlugin() {
+ plugin = this;
+ }
+
+ /**
+ * This method is called upon plug-in activation
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ }
+
+ /**
+ * This method is called when the plug-in is stopped
+ */
+ public void stop(BundleContext context) throws Exception {
+ super.stop(context);
+ plugin = null;
+ }
+
+ /**
+ * Returns the shared instance.
+ */
+ public static MspPlugin getDefault() {
+ return plugin;
+ }
+
+ /**
+ * Returns an image descriptor for the image file at the given plug-in
+ * relative path.
+ *
+ * @param path
+ * the path
+ * @return the image descriptor
+ */
+ public static ImageDescriptor getImageDescriptor(String path) {
+ return AbstractUIPlugin.imageDescriptorFromPlugin(
+ "org.eclipse.actf.ai.tts.msp", path); //$NON-NLS-1$
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpNotifySource.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpNotifySource.java
new file mode 100644
index 0000000..66de1a6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpNotifySource.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.engine;
+
+import org.eclipse.actf.ai.voice.IVoiceEventListener;
+import org.eclipse.actf.util.win32.COMUtil;
+import org.eclipse.swt.internal.Callback;
+import org.eclipse.swt.internal.ole.win32.GUID;
+import org.eclipse.swt.internal.ole.win32.IDispatch;
+import org.eclipse.swt.ole.win32.OLE;
+
+/**
+ * COM wrapper of ISpNotifySource interface.
+ *
+ * @see "Microsoft Speech API ISpNotifySource"
+ */
+public class ISpNotifySource extends IDispatch {
+
+ public static final GUID IID = COMUtil
+ .IIDFromString("{5EFF4AEF-8487-11D2-961C-00C04F8EE628}"); //$NON-NLS-1$
+
+ public static final int SPEI_START_INPUT_STREAM = 1;
+ public static final int SPEI_END_INPUT_STREAM = 2;
+ public static final int SPEI_VOICE_CHANGE = 3;
+ public static final int SPEI_TTS_BOOKMARK = 4;
+ public static final int SPEI_WORD_BOUNDARY = 5;
+ public static final int SPEI_PHONEME = 6;
+ public static final int SPEI_SENTENCE_BOUNDARY = 7;
+ public static final int SPEI_VISEME = 8;
+ public static final int SPEI_TTS_AUDIO_LEVEL = 9;
+
+ private int address;
+ private Callback callback = null;
+ private IVoiceEventListener eventListener = null;
+
+ public ISpNotifySource(int address) {
+ super(address);
+ this.address = address;
+ callback = new Callback(this, "SAPINotifyCallback", 2); //$NON-NLS-1$
+ SetNotifyCallbackFunction(callback.getAddress(), 0, 0);
+ SetInterest(1 << SPEI_TTS_BOOKMARK, 1 << SPEI_TTS_BOOKMARK);
+ }
+
+ public static ISpNotifySource getNotifySource(ISpVoice dispatch) {
+ int[] ppv = new int[1];
+ if (OLE.S_OK == dispatch.QueryInterface(IID, ppv)) {
+ return new ISpNotifySource(ppv[0]);
+ }
+ return null;
+ }
+
+ public void setEventListener(IVoiceEventListener eventListener) {
+ this.eventListener = eventListener;
+ }
+
+ int SAPINotifyCallback(int wParam, int lParam) {
+ SpEvent se = new SpEvent();
+ try {
+ while (OLE.S_OK == GetEvent(se.getAddress())) {
+ if (null != eventListener) {
+ if (SPEI_TTS_BOOKMARK == se.getEventId()) {
+ eventListener.indexReceived(se.getWParam());
+ }
+ continue;
+ }
+ String eventName;
+ switch (se.getEventId()) {
+ case SPEI_START_INPUT_STREAM:
+ eventName = "SPEI_START_INPUT_STREAM"; //$NON-NLS-1$
+ break;
+ case SPEI_END_INPUT_STREAM:
+ eventName = "SPEI_END_INPUT_STREAM"; //$NON-NLS-1$
+ break;
+ case SPEI_VOICE_CHANGE:
+ eventName = "SPEI_VOICE_CHANGE"; //$NON-NLS-1$
+ break;
+ case SPEI_TTS_BOOKMARK:
+ eventName = "SPEI_TTS_BOOKMARK"; //$NON-NLS-1$
+ break;
+ case SPEI_WORD_BOUNDARY:
+ eventName = "SPEI_WORD_BOUNDARY"; //$NON-NLS-1$
+ break;
+ case SPEI_PHONEME:
+ eventName = "SPEI_PHONEME"; //$NON-NLS-1$
+ break;
+ case SPEI_SENTENCE_BOUNDARY:
+ eventName = "SPEI_SENTENCE_BOUNDARY"; //$NON-NLS-1$
+ break;
+ case SPEI_VISEME:
+ eventName = "SPEI_VISEME"; //$NON-NLS-1$
+ break;
+ case SPEI_TTS_AUDIO_LEVEL:
+ eventName = "SPEI_TTS_AUDIO_LEVEL"; //$NON-NLS-1$
+ break;
+ default:
+ eventName = "Unknown+(" + se.getEventId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ break;
+ }
+ System.out
+ .println(eventName
+ + ": " + se.getLParamType() + "/" + se.getStreamNum() + "/" + se.getAudioStreamOffset() + "/" + se.getLParam() + "/" + se.getWParam()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+ }
+ } finally {
+ se.dispose();
+ }
+ return 0;
+ }
+
+ public int SetNotifyCallbackFunction(int pCallbackAddress, int wParam,
+ int lParam) {
+ return COMUtil.VtblCall(5, address, pCallbackAddress, wParam, lParam);
+ }
+
+ public int SetInterest(int eventInterest, int queuedInterest) {
+ return COMUtil.VtblCall(10, address, 0x40000000 | eventInterest, 2,
+ 0x40000000 | queuedInterest, 2);
+ }
+
+ public int GetEvent(int pSPEVENTAddress) {
+ return COMUtil.VtblCall(11, address, 1, pSPEVENTAddress, 0);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java
new file mode 100644
index 0000000..898ac3c
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.tts.msp.engine;
+
+import org.eclipse.actf.util.win32.COMUtil;
+import org.eclipse.swt.internal.ole.win32.GUID;
+import org.eclipse.swt.internal.ole.win32.IDispatch;
+
+/**
+ * COM wrapper of ISpVoice interface.
+ *
+ * @see "Microsoft Speech API ISpVoice"
+ */
+public class ISpVoice extends IDispatch {
+
+ public static final GUID IID = COMUtil
+ .IIDFromString("{d941651c-44e6-4c17-badf-c36826fc3424}"); //$NON-NLS-1$
+
+ private int address;
+
+ public ISpVoice(int address) {
+ super(address);
+ this.address = address;
+ }
+
+ public int put_Voice(int pVoiceAddress) {
+ return COMUtil.VtblCall(9, address, pVoiceAddress);
+ }
+
+ public int put_AudioOutput(int pAudioOutputAddress) {
+ return COMUtil.VtblCall(11, address, pAudioOutputAddress);
+ }
+
+ public int get_Rate(int pRateAddress) {
+ return COMUtil.VtblCall(14, address, pRateAddress);
+ }
+
+ public int put_Rate(int rate) {
+ return COMUtil.VtblCall(15, address, rate);
+ }
+
+ public int Speak(int pTextAddress, int flags) {
+ return COMUtil.VtblCall(28, address, pTextAddress, flags, 0);
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java
new file mode 100644
index 0000000..eba32ea
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java
@@ -0,0 +1,389 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.engine;
+
+import org.eclipse.actf.ai.tts.ISAPIEngine;
+import org.eclipse.actf.ai.tts.msp.MspPlugin;
+import org.eclipse.actf.ai.voice.IVoiceEventListener;
+import org.eclipse.actf.util.win32.COMUtil;
+import org.eclipse.actf.util.win32.MemoryUtil;
+import org.eclipse.actf.util.win32.NativeIntAccess;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.Variant;
+
+/**
+ * The implementation of ITTSEngine to use Microsoft Speech API.
+ */
+public class MspVoice implements ISAPIEngine, IPropertyChangeListener {
+
+ public static final String ID = "org.eclipse.actf.ai.tts.msp.engine.MspVoice"; //$NON-NLS-1$
+ public static final String AUDIO_OUTPUT = "org.eclipse.actf.ai.tts.MspVoice.audioOutput"; //$NON-NLS-1$
+
+ public ISpVoice dispSpVoice;
+ private Variant varSapiVoice;
+ private OleAutomation automation;
+ private int idGetVoices;
+ private int idGetAudioOutputs;
+ private ISpNotifySource spNotifySource = null;
+ private static IPreferenceStore preferenceStore = MspPlugin.getDefault()
+ .getPreferenceStore();
+ private boolean isDisposed = false;
+
+ public MspVoice() {
+ int pv = COMUtil.createDispatch(ISpVoice.IID);
+ dispSpVoice = new ISpVoice(pv);
+ varSapiVoice = new Variant(dispSpVoice);
+ automation = varSapiVoice.getAutomation();
+ spNotifySource = ISpNotifySource.getNotifySource(dispSpVoice);
+ MspPlugin.getDefault().addPropertyChangeListener(this);
+
+ idGetVoices = getIDsOfNames("GetVoices"); //$NON-NLS-1$
+ idGetAudioOutputs = getIDsOfNames("GetAudioOutputs"); //$NON-NLS-1$
+
+ // init by using default engine to avoid init error of some TTS engines
+ String orgID = preferenceStore.getString(ID);
+ preferenceStore.setValue(ID, preferenceStore.getDefaultString(ID));
+ setAudioOutputName();
+ // switch to actual engine
+ preferenceStore.setValue(ID, orgID);
+ // setVoiceName();
+
+ // to avoid access violation error at application shutdown
+ stop();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ if (ID.equals(event.getProperty())) {
+ stop();
+ setVoiceName();
+ } else if (AUDIO_OUTPUT.equals(event.getProperty())) {
+ stop();
+ setAudioOutputName();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.ai.voice.IVoiceEventListener)
+ */
+ public void setEventListener(IVoiceEventListener eventListener) {
+ spNotifySource.setEventListener(eventListener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#speak(java.lang.String, int, int)
+ */
+ public void speak(String text, int flags, int index) {
+ int firstFlag = SVSFlagsAsync;
+ if (0 != (TTSFLAG_FLUSH & flags)) {
+ firstFlag |= SVSFPurgeBeforeSpeak;
+ }
+ if (index >= 0) {
+ speak(
+ "<BOOKMARK mark=\"" + index + "\"/>", firstFlag | SVSFPersistXML); //$NON-NLS-1$ //$NON-NLS-2$
+ speak(text, SVSFlagsAsync);
+ speak("<BOOKMARK mark=\"-1\"/>", SVSFlagsAsync | SVSFPersistXML); //$NON-NLS-1$
+ } else {
+ speak(text, firstFlag);
+ }
+ }
+
+ public void speak(String text, int sapiFlags) {
+ char[] data = (text + "\0").toCharArray(); //$NON-NLS-1$
+ int bstrText = MemoryUtil.SysAllocString(data);
+ try {
+ dispSpVoice.Speak(bstrText, sapiFlags);
+ } finally {
+ MemoryUtil.SysFreeString(bstrText);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#stop()
+ */
+ public void stop() {
+ speak("", TTSFLAG_FLUSH, -1); //$NON-NLS-1$
+ }
+
+ /**
+ * @param rate
+ * The rate property to be set.
+ * @return The invocation is succeeded then it returns true.
+ */
+ public boolean setRate(int rate) {
+ return OLE.S_OK == dispSpVoice.put_Rate(rate);
+ }
+
+ /**
+ * @return The rate property of the voice engine.
+ */
+ public int getRate() {
+ NativeIntAccess nia = new NativeIntAccess();
+ try {
+ if (OLE.S_OK == dispSpVoice.get_Rate(nia.getAddress())) {
+ return nia.getInt();
+ }
+ } finally {
+ nia.dispose();
+ }
+ return -1;
+ }
+
+ /**
+ * @param varVoice
+ * The voice object to be set.
+ * @return The invocation is succeeded then it returns true.
+ */
+ public boolean setVoice(Variant varVoice) {
+ return OLE.S_OK == dispSpVoice.put_Voice(varVoice.getDispatch()
+ .getAddress());
+ }
+
+ /**
+ * @param varAudioOutput
+ * The audio output object to be set.
+ * @return The invocation is succeeded then it returns true.
+ */
+ public boolean setAudioOutput(Variant varAudioOutput) {
+ return OLE.S_OK == dispSpVoice
+ .put_AudioOutput(null != varAudioOutput ? varAudioOutput
+ .getDispatch().getAddress() : 0);
+ }
+
+ private void setVoiceName() {
+ String voiceName = preferenceStore.getString(ID);
+ if (voiceName.length() > 0) {
+ setVoiceName("name=" + voiceName); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @param voiceName
+ * The voice name to be set.
+ * @return The invocation is succeeded then it returns true.
+ */
+ public boolean setVoiceName(String voiceName) {
+ boolean success = false;
+ Variant varVoices = getVoices(voiceName, null);
+ if (null != varVoices) {
+ SpeechObjectTokens tokens = SpeechObjectTokens.getTokens(varVoices);
+ if (null != tokens && 0 < tokens.getCount()) {
+ Variant varVoice = tokens.getItem(0);
+ if (null != varVoice) {
+ success = setVoice(varVoice);
+ }
+ }
+ varVoices.dispose();
+ }
+ if (!success) {
+ int index = voiceName.indexOf("name="); //$NON-NLS-1$
+ varVoices = getVoices(null, null);
+ if (null != varVoices && index > -1) {
+ String name = voiceName.substring(index + 5);
+ SpeechObjectTokens voiceTokens = SpeechObjectTokens
+ .getTokens(varVoices);
+ if (null != voiceTokens) {
+ int count = voiceTokens.getCount();
+ for (int i = 0; i < count; i++) {
+ Variant varVoice = voiceTokens.getItem(i);
+ if (null != varVoice) {
+ SpObjectToken token = SpObjectToken
+ .getToken(varVoice);
+ if (null != token
+ && name.equals(token.getDescription(0))) {
+ success = setVoice(varVoice);
+ }
+ }
+ }
+ }
+ }
+ varVoices.dispose();
+ }
+ return success;
+ }
+
+ private void setAudioOutputName() {
+ String audioOutput = preferenceStore.getString(AUDIO_OUTPUT);
+ if (audioOutput.length() > 0) {
+ setAudioOutputName(audioOutput);
+ } else {
+ setAudioOutput(null);
+ }
+ }
+
+ /**
+ * @param audioOutput
+ * The audio output name to be set.
+ * @return The invocation is succeeded then it returns true.
+ */
+ public boolean setAudioOutputName(String audioOutput) {
+ boolean success = false;
+ Variant varAudioOutputs = getAudioOutputs(null, null);
+ if (null != varAudioOutputs) {
+ SpeechObjectTokens tokens = SpeechObjectTokens
+ .getTokens(varAudioOutputs);
+ if (null != tokens) {
+ for (int i = 0; i < tokens.getCount(); i++) {
+ Variant varAudioOutput = tokens.getItem(i);
+ if (null != varAudioOutput) {
+ SpObjectToken token = SpObjectToken
+ .getToken(varAudioOutput);
+ if (null != token
+ && audioOutput.equals(token.getDescription(0))) {
+ success = setAudioOutput(varAudioOutput);
+ break;
+ }
+ }
+ }
+ }
+ varAudioOutputs.dispose();
+ }
+ return success;
+ }
+
+ /**
+ * @param requiredAttributes
+ * @param optionalAttributes
+ * @return The tokens of voices.
+ */
+ public Variant getVoices(String requiredAttributes,
+ String optionalAttributes) {
+ return getTokens(idGetVoices, requiredAttributes, optionalAttributes);
+ }
+
+ /**
+ * @param requiredAttributes
+ * @param optionalAttributes
+ * @return The tokens of audio outputs.
+ */
+ public Variant getAudioOutputs(String requiredAttributes,
+ String optionalAttributes) {
+ return getTokens(idGetAudioOutputs, requiredAttributes,
+ optionalAttributes);
+ }
+
+ private Variant getTokens(int id, String requiredAttributes,
+ String optionalAttributes) {
+ if (null == requiredAttributes) {
+ return automation.invoke(id);
+ } else if (null == optionalAttributes) {
+ return automation.invoke(id, new Variant[] { new Variant(
+ requiredAttributes) });
+ }
+ return automation.invoke(id, new Variant[] {
+ new Variant(requiredAttributes),
+ new Variant(optionalAttributes) });
+ }
+
+ private int getIDsOfNames(String name) {
+ int dispid[] = automation.getIDsOfNames(new String[] { name });
+ if (null != dispid) {
+ return dispid[0];
+ }
+ return 0;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#dispose()
+ */
+ public void dispose() {
+ if (!isDisposed) {
+ isDisposed = true;
+
+ varSapiVoice.dispose();
+
+ if (MspPlugin.getDefault() != null) {
+ MspPlugin.getDefault().removePropertyChangeListener(this);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#getSpeed()
+ */
+ public int getSpeed() {
+ int rate = getRate(); // -10 <= rate <= 10
+ return (rate + 10) * 5; // 0 <= speed <= 100
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#setSpeed(int)
+ */
+ public void setSpeed(int speed) {
+ int rate = speed / 5 - 10;
+ setRate(rate);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#setLanguage(java.lang.String)
+ */
+ public void setLanguage(String language) {
+ String token;
+ if (LANG_JAPANESE.equals(language)) {
+ token = "language=411"; //$NON-NLS-1$
+ } else if (LANG_ENGLISH.equals(language)) {
+ token = "language=409;9"; //$NON-NLS-1$
+ } else {
+ return;
+ }
+ setVoiceName(token);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#setGender(java.lang.String)
+ */
+ public void setGender(String gender) {
+ //TODO
+ if(GENDER_MALE.equalsIgnoreCase(gender)){
+// setVoiceName("name=Microsoft Mike");
+ }else if(GENDER_FEMALE.equalsIgnoreCase(gender)){
+// setVoiceName("name=Microsoft Mary");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.actf.ai.tts.ITTSEngine#isAvailable()
+ */
+ public boolean isAvailable() {
+ return automation != null;
+ }
+
+ public boolean isDisposed() {
+ return isDisposed;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpEvent.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpEvent.java
new file mode 100644
index 0000000..0c3e84a
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpEvent.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.engine;
+
+import org.eclipse.actf.util.win32.MemoryUtil;
+
+/**
+ * COM wrapper of SPEVENT structure.
+ *
+ * @see "Microsoft Speech API SPEVENT"
+ */
+public class SpEvent {
+
+ private int address = MemoryUtil.GlobalAlloc(24);
+
+ public int getAddress() {
+ return address;
+ }
+
+ public short getEventId() {
+ short[] eventId = new short[1];
+ MemoryUtil.MoveMemory(eventId, address, 2);
+ return eventId[0];
+ }
+
+ public short getLParamType() {
+ short[] lParamType = new short[1];
+ MemoryUtil.MoveMemory(lParamType, address + 2, 2);
+ return lParamType[0];
+ }
+
+ public int getStreamNum() {
+ int[] streamNum = new int[1];
+ MemoryUtil.MoveMemory(streamNum, address + 4, 4);
+ return streamNum[0];
+ }
+
+ public long getAudioStreamOffset() {
+ int[] audioStreamOffset = new int[2];
+ MemoryUtil.MoveMemory(audioStreamOffset, address + 8, 4 * 2);
+ return audioStreamOffset[0]
+ + ((long) audioStreamOffset[1] << 32);
+ }
+
+ public int getWParam() {
+ int[] wParam = new int[1];
+ MemoryUtil.MoveMemory(wParam, address + 16, 4);
+ return wParam[0];
+ }
+
+ public int getLParam() {
+ int[] lParam = new int[1];
+ MemoryUtil.MoveMemory(lParam, address + 20, 4);
+ return lParam[0];
+ }
+
+ public void dispose() {
+ MemoryUtil.GlobalFree(address);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpObjectToken.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpObjectToken.java
new file mode 100644
index 0000000..5402f12
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpObjectToken.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.engine;
+
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.Variant;
+
+/*
+ * COM Wrapper of SpObjectToken interface
+ *
+ * @see "Microsoft Speech API SpObjectToken"
+ */
+public class SpObjectToken {
+
+ private OleAutomation automation;
+ private int idGetDescription;
+
+ public SpObjectToken(Variant varToken) {
+ automation = varToken.getAutomation();
+ idGetDescription = getIDsOfNames("GetDescription"); //$NON-NLS-1$
+ }
+
+ public static SpObjectToken getToken(Variant varToken) {
+ if (null == varToken || OLE.VT_DISPATCH != varToken.getType()) {
+ return null;
+ }
+ return new SpObjectToken(varToken);
+ }
+
+ public String getDescription(int locale) {
+ try {
+ return automation.invoke(idGetDescription,
+ new Variant[] { new Variant(locale) }).getString().trim();
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ private int getIDsOfNames(String name) {
+ int dispid[] = automation.getIDsOfNames(new String[] { name });
+ if (null != dispid) {
+ return dispid[0];
+ }
+ return 0;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpeechObjectTokens.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpeechObjectTokens.java
new file mode 100644
index 0000000..d5f834f
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/SpeechObjectTokens.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.engine;
+
+import org.eclipse.swt.ole.win32.OLE;
+import org.eclipse.swt.ole.win32.OleAutomation;
+import org.eclipse.swt.ole.win32.Variant;
+
+/*
+ * COM Wrapper of ISpeechObjectTokens interface
+ *
+ * @see "Microsoft Speech API ISpeechObjectTokens"
+ */
+public class SpeechObjectTokens {
+
+ private OleAutomation automation;
+ private int idCount;
+ private int idItem;
+
+ public SpeechObjectTokens(Variant varTokens) {
+ automation = varTokens.getAutomation();
+ idCount = getIDsOfNames("Count"); //$NON-NLS-1$
+ idItem = getIDsOfNames("Item"); //$NON-NLS-1$
+ }
+
+ public static SpeechObjectTokens getTokens(Variant varTokens) {
+ if (null == varTokens || OLE.VT_DISPATCH != varTokens.getType()) {
+ return null;
+ }
+ return new SpeechObjectTokens(varTokens);
+ }
+
+ public int getCount() {
+ try {
+ return automation.getProperty(idCount).getInt();
+ } catch (Exception e) {
+ }
+ return 0;
+ }
+
+ public Variant getItem(int index) {
+ try {
+ return automation.invoke(idItem,
+ new Variant[] { new Variant(index) });
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ private int getIDsOfNames(String name) {
+ int dispid[] = automation.getIDsOfNames(new String[] { name });
+ if (null != dispid) {
+ return dispid[0];
+ }
+ return 0;
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspAudioOutputFieldEditor.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspAudioOutputFieldEditor.java
new file mode 100644
index 0000000..9a19e2d
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspAudioOutputFieldEditor.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.tts.msp.preferences;
+
+import org.eclipse.actf.ai.tts.msp.MspPlugin;
+import org.eclipse.actf.ai.tts.msp.engine.MspVoice;
+import org.eclipse.actf.ai.voice.preferences.util.ComboFieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Composite;
+
+public class MspAudioOutputFieldEditor extends ComboFieldEditor {
+
+ private static IPreferenceStore preferenceStore = MspPlugin.getDefault()
+ .getPreferenceStore();
+
+ public MspAudioOutputFieldEditor(String labelText, Composite parent) {
+ super(MspVoice.AUDIO_OUTPUT, labelText, null, parent);
+ }
+
+ protected void initLabelsAndValues(String[][] labelsAndValues) {
+ super.initLabelsAndValues(MspTestManager.getInstance()
+ .getAudioOutputNames());
+ }
+
+ @Override
+ protected void fireValueChanged(String property, Object oldValue,
+ Object newValue) {
+
+ preferenceStore.setValue(MspVoice.AUDIO_OUTPUT, newValue.toString());
+
+ super.fireValueChanged(property, oldValue, newValue);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspPreferenceInitializer.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspPreferenceInitializer.java
new file mode 100644
index 0000000..33c90a7
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspPreferenceInitializer.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.preferences;
+
+import org.eclipse.actf.ai.tts.msp.MspPlugin;
+import org.eclipse.actf.ai.tts.msp.engine.MspVoice;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+
+public class MspPreferenceInitializer extends AbstractPreferenceInitializer {
+
+ public void initializeDefaultPreferences() {
+ IPreferenceStore store = MspPlugin.getDefault().getPreferenceStore();
+ store.setDefault(MspVoice.ID, "Microsoft Sam"); //$NON-NLS-1$
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspPreferencePage.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspPreferencePage.java
new file mode 100644
index 0000000..35697c6
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspPreferencePage.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.actf.ai.tts.msp.preferences;
+
+import org.eclipse.actf.ai.tts.TTSRegistry;
+import org.eclipse.actf.ai.tts.msp.Messages;
+import org.eclipse.actf.ai.tts.msp.MspPlugin;
+import org.eclipse.actf.ai.tts.msp.engine.MspVoice;
+import org.eclipse.actf.ai.voice.preferences.util.ComboFieldEditor;
+import org.eclipse.actf.ai.voice.preferences.util.GroupFieldEditorVoicePreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+
+public class MspPreferencePage extends GroupFieldEditorVoicePreferencePage
+ implements IWorkbenchPreferencePage {
+
+ private String orgVoice;
+ private String orgAudio;
+
+ public MspPreferencePage() {
+ super();
+ setDescription(Messages.tts_msp_description);
+ setPreferenceStore(MspPlugin.getDefault().getPreferenceStore());
+ }
+
+ public void createFieldEditors() {
+ if (!TTSRegistry.isAvailable(MspVoice.ID)) {
+ setMessage(Messages.tts_msp_notAvailable);
+ return;
+ }
+
+ orgVoice = getPreferenceStore().getString(MspVoice.ID);
+ orgAudio = getPreferenceStore().getString(MspVoice.AUDIO_OUTPUT);
+
+ final ComboFieldEditor voiceEditor;
+ addField(voiceEditor = new MspVoiceFieldEditor(
+ Messages.tts_msp_voicename, getFieldEditorParent()));
+ addField(new MspAudioOutputFieldEditor(Messages.tts_msp_audiooutput,
+ getFieldEditorParent()));
+
+ Composite comp = new Composite(getFieldEditorParent(), SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = layout.marginWidth = 0;
+ comp.setLayout(layout);
+ GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
+ gd.horizontalSpan = voiceEditor.getNumberOfControls();
+ comp.setLayoutData(gd);
+
+ Button testButton = new Button(comp, SWT.NONE);
+ testButton.setText(Messages.tts_msp_test);
+ testButton.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ MspTestManager.getInstance().speakTest();
+ }
+ });
+ }
+
+ public void init(IWorkbench workbench) {
+ }
+
+ @Override
+ public boolean performCancel() {
+ getPreferenceStore().setValue(MspVoice.ID, orgVoice);
+ getPreferenceStore().setValue(MspVoice.AUDIO_OUTPUT, orgAudio);
+ return super.performCancel();
+ }
+
+ @Override
+ protected void performApply() {
+ super.performApply();
+
+ orgVoice = getPreferenceStore().getString(MspVoice.ID);
+ orgAudio = getPreferenceStore().getString(MspVoice.AUDIO_OUTPUT);
+ }
+
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspTestManager.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspTestManager.java
new file mode 100644
index 0000000..7cf26f8
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspTestManager.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.tts.msp.preferences;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.actf.ai.tts.ISAPIEngine;
+import org.eclipse.actf.ai.tts.TTSRegistry;
+import org.eclipse.actf.ai.tts.msp.MspPlugin;
+import org.eclipse.actf.ai.tts.msp.engine.MspVoice;
+import org.eclipse.actf.ai.tts.msp.engine.SpObjectToken;
+import org.eclipse.actf.ai.tts.msp.engine.SpeechObjectTokens;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.swt.ole.win32.Variant;
+
+public class MspTestManager {
+
+ private static MspTestManager instance;
+
+ private MspVoice sapiVoice;
+ private String[][] voiceNames;
+ private String[][] audioOutputNames;
+
+ private static final String SAMPLE_TEXT = "Hello. This is test."; //$NON-NLS-1$
+
+ public MspTestManager() {
+ sapiVoice = (MspVoice) TTSRegistry.createTTSEngine(MspVoice.ID);
+ Variant varVoices = sapiVoice.getVoices(null, null);
+ if (null != varVoices) {
+ SpeechObjectTokens voiceTokens = SpeechObjectTokens
+ .getTokens(varVoices);
+ if (null != voiceTokens) {
+ String exclude = Platform.getResourceString(MspPlugin
+ .getDefault().getBundle(), "%voice.exclude"); //$NON-NLS-1$
+ List<String[]> voiceList = new ArrayList<String[]>();
+ int count = voiceTokens.getCount();
+ for (int i = 0; i < count; i++) {
+ Variant varVoice = voiceTokens.getItem(i);
+ if (null != varVoice) {
+ SpObjectToken token = SpObjectToken.getToken(varVoice);
+ if (null != token) {
+ String voiceName = token.getDescription(0);
+ if (null == exclude || !exclude.equals(voiceName)) {
+ voiceList.add(new String[] { voiceName,
+ voiceName });
+ }
+ }
+ }
+ }
+ voiceNames = voiceList.toArray(new String[voiceList.size()][]);
+ }
+ varVoices.dispose();
+ }
+ Variant varAudioOutputs = sapiVoice.getAudioOutputs(null, null);
+ if (null != varAudioOutputs) {
+ SpeechObjectTokens audioOutputTokens = SpeechObjectTokens
+ .getTokens(varAudioOutputs);
+ if (null != audioOutputTokens) {
+ List<String[]> audioOutputList = new ArrayList<String[]>();
+ int count = audioOutputTokens.getCount();
+ for (int i = 0; i < count; i++) {
+ Variant varAudioOutput = audioOutputTokens.getItem(i);
+ if (null != varAudioOutput) {
+ SpObjectToken token = SpObjectToken
+ .getToken(varAudioOutput);
+ if (null != token) {
+ String audioOutputName = token.getDescription(0);
+ audioOutputList.add(new String[] { audioOutputName,
+ audioOutputName });
+ }
+ }
+ }
+ audioOutputNames = audioOutputList
+ .toArray(new String[audioOutputList.size()][]);
+ }
+ varAudioOutputs.dispose();
+ }
+ }
+
+ public static MspTestManager getInstance() {
+ if (null == instance) {
+ instance = new MspTestManager();
+ }
+ return instance;
+ }
+
+ public String[][] getVoiceNames() {
+ return voiceNames;
+ }
+
+ public String getVoiceName(int index) {
+ if (null != voiceNames && index < voiceNames.length) {
+ return voiceNames[index][1];
+ }
+ return null;
+ }
+
+ public String[][] getAudioOutputNames() {
+ return audioOutputNames;
+ }
+
+ public String getAudioOutputName(int index) {
+ if (null != audioOutputNames && index < audioOutputNames.length) {
+ return audioOutputNames[index][1];
+ }
+ return null;
+ }
+
+ public void speakTest() {
+ sapiVoice.speak(SAMPLE_TEXT, ISAPIEngine.SVSFDefault);
+ }
+}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspVoiceFieldEditor.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspVoiceFieldEditor.java
new file mode 100644
index 0000000..3b321b9
--- /dev/null
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/preferences/MspVoiceFieldEditor.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.actf.ai.tts.msp.preferences;
+
+import org.eclipse.actf.ai.tts.msp.MspPlugin;
+import org.eclipse.actf.ai.tts.msp.engine.MspVoice;
+import org.eclipse.actf.ai.voice.preferences.util.ComboFieldEditor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Composite;
+
+public class MspVoiceFieldEditor extends ComboFieldEditor {
+
+ private static IPreferenceStore preferenceStore = MspPlugin.getDefault()
+ .getPreferenceStore();
+
+ public MspVoiceFieldEditor(String labelText, Composite parent) {
+ super(MspVoice.ID, labelText, null, parent);
+ }
+
+ protected void initLabelsAndValues(String[][] labelsAndValues) {
+ super
+ .initLabelsAndValues(MspTestManager.getInstance()
+ .getVoiceNames());
+ }
+
+ @Override
+ protected void fireValueChanged(String property, Object oldValue,
+ Object newValue) {
+
+ preferenceStore.setValue(MspVoice.ID, newValue.toString());
+
+ super.fireValueChanged(property, oldValue, newValue);
+ }
+
+}