From f1ff6ad856decb1a50b0d01be7d36af48c339816 Mon Sep 17 00:00:00 2001 From: Ingmar Steiner Date: Fri, 19 Dec 2014 13:09:01 +0100 Subject: [PATCH] format java code in marytts-client incantation: $ mvn com.googlecode.maven-java-formatter-plugin:maven-java-formatter-plugin:format -pl marytts-client --- .../client/AudioEffectControlData.java | 118 +- .../marytts/client/AudioEffectControlGUI.java | 277 +- .../marytts/client/AudioEffectsBoxData.java | 196 +- .../marytts/client/AudioEffectsBoxGUI.java | 270 +- .../main/java/marytts/client/BatchSynth.java | 193 +- .../main/java/marytts/client/MaryClient.java | 1866 +++++------ .../java/marytts/client/MaryFormData.java | 1278 ++++---- .../java/marytts/client/MaryGUIClient.java | 2842 ++++++++--------- .../marytts/client/MaryInterfaceApplet.java | 84 +- .../marytts/client/http/MaryHttpClient.java | 1196 +++---- .../AsynchronousThreadedMaryClient.java | 200 +- .../tools/emospeak/AudioFileReceiver.java | 11 +- .../java/marytts/tools/emospeak/EmoSpeak.java | 93 +- .../tools/emospeak/EmoSpeakApplet.java | 69 +- .../marytts/tools/emospeak/EmoSpeakPanel.java | 1166 ++++--- .../tools/emospeak/EmoTransformer.java | 223 +- .../tools/emospeak/JFeeltraceCircle.java | 364 ++- .../tools/emospeak/JFeeltracePanel.java | 331 +- .../tools/emospeak/ProsodyXMLDisplayer.java | 11 +- .../RectangularTwoDimensionalModel.java | 225 +- .../tools/emospeak/TwoDimensionalModel.java | 87 +- 21 files changed, 5536 insertions(+), 5564 deletions(-) diff --git a/marytts-client/src/main/java/marytts/client/AudioEffectControlData.java b/marytts-client/src/main/java/marytts/client/AudioEffectControlData.java index f7c3da43..48cd2641 100644 --- a/marytts-client/src/main/java/marytts/client/AudioEffectControlData.java +++ b/marytts-client/src/main/java/marytts/client/AudioEffectControlData.java @@ -1,6 +1,6 @@ -/** - * Copyright 2007 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. +/** + * Copyright 2007 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * @@ -17,46 +17,74 @@ * along with this program. If not, see . * */ -package marytts.client; - - -/** - * Data for an audio effect control. - * - * @author Oytun Türk - * - */ -public class AudioEffectControlData { - private String effectName; - private String helpText; - private String exampleParams; - private String params; - private boolean isSelected; - - public AudioEffectControlData(String strEffectNameIn, String strExampleParams, String strHelpTextIn) - { - init(strEffectNameIn, strExampleParams, strHelpTextIn); - } - - public void init(String strEffectNameIn, String strExampleParamsIn, String strHelpTextIn) - { - setEffectName(strEffectNameIn); - setExampleParams(strExampleParamsIn); - setHelpText(strHelpTextIn); - setEffectParamsToExample(); - } - - public void setEffectName(String strEffectName) { effectName = strEffectName; } - public String getEffectName() { return effectName; } - public void setHelpText(String strHelpText) { helpText = strHelpText; } - public String getHelpText() { return helpText; } - public void setParams(String strParams) { params = strParams; } - public String getParams() { return params; } - public void setExampleParams(String strExampleParams) { exampleParams = strExampleParams; } - public String getExampleParams() { return exampleParams; } - public void setEffectParamsToExample() { setParams(exampleParams); } - public void setSelected(boolean bSelected) { isSelected = bSelected; } - public boolean getSelected() { return isSelected; } - -} +package marytts.client; +/** + * Data for an audio effect control. + * + * @author Oytun Türk + * + */ +public class AudioEffectControlData { + private String effectName; + private String helpText; + private String exampleParams; + private String params; + private boolean isSelected; + + public AudioEffectControlData(String strEffectNameIn, String strExampleParams, String strHelpTextIn) { + init(strEffectNameIn, strExampleParams, strHelpTextIn); + } + + public void init(String strEffectNameIn, String strExampleParamsIn, String strHelpTextIn) { + setEffectName(strEffectNameIn); + setExampleParams(strExampleParamsIn); + setHelpText(strHelpTextIn); + setEffectParamsToExample(); + } + + public void setEffectName(String strEffectName) { + effectName = strEffectName; + } + + public String getEffectName() { + return effectName; + } + + public void setHelpText(String strHelpText) { + helpText = strHelpText; + } + + public String getHelpText() { + return helpText; + } + + public void setParams(String strParams) { + params = strParams; + } + + public String getParams() { + return params; + } + + public void setExampleParams(String strExampleParams) { + exampleParams = strExampleParams; + } + + public String getExampleParams() { + return exampleParams; + } + + public void setEffectParamsToExample() { + setParams(exampleParams); + } + + public void setSelected(boolean bSelected) { + isSelected = bSelected; + } + + public boolean getSelected() { + return isSelected; + } + +} diff --git a/marytts-client/src/main/java/marytts/client/AudioEffectControlGUI.java b/marytts-client/src/main/java/marytts/client/AudioEffectControlGUI.java index d426090b..20a5f15b 100644 --- a/marytts-client/src/main/java/marytts/client/AudioEffectControlGUI.java +++ b/marytts-client/src/main/java/marytts/client/AudioEffectControlGUI.java @@ -1,6 +1,6 @@ -/** - * Copyright 2007 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. +/** + * Copyright 2007 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * @@ -17,140 +17,139 @@ * along with this program. If not, see . * */ -package marytts.client; - -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.WindowEvent; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.JTextArea; -import javax.swing.JTextField; - - -/** - * - * An AudioEffectControlGUI consists of a checkbox, a text pane, a text field, and a button. - *

- * The checkbox indicates whether the effect will be applied or not. - *

- * The label contains the name of the effect. - *

- * The text field contains the parameters of the effect. - *

- * The button shows help information about the usage of the effect when clicked. - *

- * - * @author Oytun Türk - */ -public class AudioEffectControlGUI { - - private AudioEffectControlData data; //All data this control has about the audio effect - public JPanel mainPanel; - public JCheckBox chkEnabled; - public JTextField txtParams; - public JButton btnHelp; - - private boolean isVisible; //This can be used for not showing a specific effect for specific voices - public boolean isHelpWindowOpen; - private JFrame helpWindow; //Window to show help context - - //Create a Mary audio effect with help text - public AudioEffectControlGUI(AudioEffectControlData dataIn) - { - data = dataIn; - - mainPanel = new JPanel(); - chkEnabled = new JCheckBox(); - txtParams = new JTextField("Parameters"); - - btnHelp = new JButton("?"); - - isVisible = true; - isHelpWindowOpen = false; - - } - - public void setVisible(boolean bShow) { isVisible = bShow; } - public boolean getVisible() { return isVisible; } - - public AudioEffectControlData getData() { return data; } - - public void show() - { - mainPanel.removeAll(); - mainPanel.validate(); - - if (isVisible) - { - GridBagLayout g = new GridBagLayout(); - GridBagConstraints c = new GridBagConstraints(); - - mainPanel.setLayout(g); - - c.fill = GridBagConstraints.HORIZONTAL; - - c.gridx = 0; - c.gridy = 0; - g.setConstraints(chkEnabled, c); - chkEnabled.setPreferredSize(new Dimension(100,25)); - chkEnabled.setText(data.getEffectName()); - chkEnabled.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - data.setSelected(((JCheckBox)e.getSource()).isSelected()); - } - }); - mainPanel.add(chkEnabled); - - c.gridx = 1; - g.setConstraints(chkEnabled, c); - txtParams.setPreferredSize(new Dimension(150,25)); - txtParams.setText(data.getParams()); - mainPanel.add(txtParams); - - c.gridx = GridBagConstraints.RELATIVE; - g.setConstraints(btnHelp, c); - btnHelp.setPreferredSize(new Dimension(45,25)); - mainPanel.add(btnHelp); - - btnHelp.addActionListener( new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (!isHelpWindowOpen) - { - isHelpWindowOpen = true; - helpWindow = new JFrame("Help: " + chkEnabled.getText() + " Effect"); - JTextArea helpTextArea = new JTextArea(data.getHelpText()); - helpTextArea.setEditable(false); - - helpWindow.getContentPane().add(helpTextArea, BorderLayout.WEST); - helpWindow.pack(); - helpWindow.setLocation(btnHelp.getLocation().x, btnHelp.getLocation().y); - helpWindow.setVisible(true); - - helpWindow.addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosing(WindowEvent winEvt) { - // Perhaps ask user if they want to save any unsaved files first. - isHelpWindowOpen = false; - } - }); - } - else - { - if (helpWindow!=null) - helpWindow.requestFocus(); - } - } - }); - } - - mainPanel.validate(); - } -} +package marytts.client; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +/** + * + * An AudioEffectControlGUI consists of a checkbox, a text pane, a text field, and a button. + *

+ * The checkbox indicates whether the effect will be applied or not. + *

+ * The label contains the name of the effect. + *

+ * The text field contains the parameters of the effect. + *

+ * The button shows help information about the usage of the effect when clicked. + *

+ * + * @author Oytun Türk + */ +public class AudioEffectControlGUI { + + private AudioEffectControlData data; // All data this control has about the audio effect + public JPanel mainPanel; + public JCheckBox chkEnabled; + public JTextField txtParams; + public JButton btnHelp; + + private boolean isVisible; // This can be used for not showing a specific effect for specific voices + public boolean isHelpWindowOpen; + private JFrame helpWindow; // Window to show help context + + // Create a Mary audio effect with help text + public AudioEffectControlGUI(AudioEffectControlData dataIn) { + data = dataIn; + + mainPanel = new JPanel(); + chkEnabled = new JCheckBox(); + txtParams = new JTextField("Parameters"); + + btnHelp = new JButton("?"); + + isVisible = true; + isHelpWindowOpen = false; + + } + + public void setVisible(boolean bShow) { + isVisible = bShow; + } + + public boolean getVisible() { + return isVisible; + } + + public AudioEffectControlData getData() { + return data; + } + + public void show() { + mainPanel.removeAll(); + mainPanel.validate(); + + if (isVisible) { + GridBagLayout g = new GridBagLayout(); + GridBagConstraints c = new GridBagConstraints(); + + mainPanel.setLayout(g); + + c.fill = GridBagConstraints.HORIZONTAL; + + c.gridx = 0; + c.gridy = 0; + g.setConstraints(chkEnabled, c); + chkEnabled.setPreferredSize(new Dimension(100, 25)); + chkEnabled.setText(data.getEffectName()); + chkEnabled.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + data.setSelected(((JCheckBox) e.getSource()).isSelected()); + } + }); + mainPanel.add(chkEnabled); + + c.gridx = 1; + g.setConstraints(chkEnabled, c); + txtParams.setPreferredSize(new Dimension(150, 25)); + txtParams.setText(data.getParams()); + mainPanel.add(txtParams); + + c.gridx = GridBagConstraints.RELATIVE; + g.setConstraints(btnHelp, c); + btnHelp.setPreferredSize(new Dimension(45, 25)); + mainPanel.add(btnHelp); + + btnHelp.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!isHelpWindowOpen) { + isHelpWindowOpen = true; + helpWindow = new JFrame("Help: " + chkEnabled.getText() + " Effect"); + JTextArea helpTextArea = new JTextArea(data.getHelpText()); + helpTextArea.setEditable(false); + + helpWindow.getContentPane().add(helpTextArea, BorderLayout.WEST); + helpWindow.pack(); + helpWindow.setLocation(btnHelp.getLocation().x, btnHelp.getLocation().y); + helpWindow.setVisible(true); + + helpWindow.addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosing(WindowEvent winEvt) { + // Perhaps ask user if they want to save any unsaved files first. + isHelpWindowOpen = false; + } + }); + } else { + if (helpWindow != null) + helpWindow.requestFocus(); + } + } + }); + } + + mainPanel.validate(); + } +} diff --git a/marytts-client/src/main/java/marytts/client/AudioEffectsBoxData.java b/marytts-client/src/main/java/marytts/client/AudioEffectsBoxData.java index e4f2409a..2d273b44 100644 --- a/marytts-client/src/main/java/marytts/client/AudioEffectsBoxData.java +++ b/marytts-client/src/main/java/marytts/client/AudioEffectsBoxData.java @@ -1,101 +1,95 @@ -/** - * Copyright 2007 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. - * - * This file is part of MARY TTS. - * - * MARY TTS is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - */ -package marytts.client; - -import marytts.util.string.StringUtils; - -/** - * Data for a set of audio effects, i.e. "an audio effects box". - * - * @author Oytun Türk - * - */ -public class AudioEffectsBoxData { - - private AudioEffectControlData[] effectControlsData; - - //availableEffects is one large string produced by the server in the following format: - // charEffectSeparator - // - // effect´s name - // example parameters string - // help text string - // - // - // effect´s name - // example parameters string - // help text string - // - // ... - // - // effect´s name - // example parameters string - // help text string - // - public AudioEffectsBoxData(String availableEffects) - { - effectControlsData = null; - - if (availableEffects!=null && availableEffects.length()>0) - parseAvailableEffects(availableEffects); - } - - public AudioEffectControlData getControlData(int index) - { - if (effectControlsData!=null && index>=0 && index. + * + */ +package marytts.client; + +import marytts.util.string.StringUtils; + +/** + * Data for a set of audio effects, i.e. "an audio effects box". + * + * @author Oytun Türk + * + */ +public class AudioEffectsBoxData { + + private AudioEffectControlData[] effectControlsData; + + // availableEffects is one large string produced by the server in the following format: + // charEffectSeparator + // + // effect´s name + // example parameters string + // help text string + // + // + // effect´s name + // example parameters string + // help text string + // + // ... + // + // effect´s name + // example parameters string + // help text string + // + public AudioEffectsBoxData(String availableEffects) { + effectControlsData = null; + + if (availableEffects != null && availableEffects.length() > 0) + parseAvailableEffects(availableEffects); + } + + public AudioEffectControlData getControlData(int index) { + if (effectControlsData != null && index >= 0 && index < effectControlsData.length) + return effectControlsData[index]; + else + return null; + } + + public boolean hasEffects() { + return effectControlsData != null; + } + + // Parse the XML-like full effect set string from the server + protected int parseAvailableEffects(String availableEffects) { + String[] effectLines = StringUtils.toStringArray(availableEffects); + effectControlsData = new AudioEffectControlData[effectLines.length]; + for (int i = 0; i < effectLines.length; i++) { + String strEffectName, strParams; + int iSpace = effectLines[i].indexOf(' '); + if (iSpace != -1) { + strEffectName = effectLines[i].substring(0, iSpace); + strParams = effectLines[i].substring(iSpace + 1); + } else { // no params + strEffectName = effectLines[i]; + strParams = ""; + } + effectControlsData[i] = new AudioEffectControlData(strEffectName, strParams, null); + } + return getTotalEffects(); + } + + public int getTotalEffects() { + if (effectControlsData != null) + return effectControlsData.length; + else + return 0; + } +} diff --git a/marytts-client/src/main/java/marytts/client/AudioEffectsBoxGUI.java b/marytts-client/src/main/java/marytts/client/AudioEffectsBoxGUI.java index 39354858..56ea2f5e 100644 --- a/marytts-client/src/main/java/marytts/client/AudioEffectsBoxGUI.java +++ b/marytts-client/src/main/java/marytts/client/AudioEffectsBoxGUI.java @@ -1,140 +1,130 @@ -/** - * Copyright 2007 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. - * - * This file is part of MARY TTS. - * - * MARY TTS is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - */ -package marytts.client; - -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JScrollPane; - -/** - * GUI for a set of audio effects. - * - * @author Oytun Türk - */ -public class AudioEffectsBoxGUI { - private AudioEffectsBoxData data; - public AudioEffectControlGUI[] effectControls; - - public JPanel mainPanel; - public JLabel effectsBoxLabel; - public JScrollPane scrollPane; - public JPanel effectControlsPanel; - - public AudioEffectsBoxGUI(String availableEffects) - { - data = new AudioEffectsBoxData(availableEffects); - - if (availableEffects!=null && !availableEffects.equals("")) - { - mainPanel = new JPanel(); - effectsBoxLabel = new JLabel("Audio Effects:"); - effectControlsPanel = new JPanel(); - - if (data.getTotalEffects()>0) - { - effectControls = new AudioEffectControlGUI[data.getTotalEffects()]; - - for (int i=0; i0) - { - effectControlsPanel.setLayout(g); - - c.gridx = 0; - c.fill = GridBagConstraints.BOTH; - - int totalShown = 0; - for (int i=0; i. + * + */ +package marytts.client; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; + +/** + * GUI for a set of audio effects. + * + * @author Oytun Türk + */ +public class AudioEffectsBoxGUI { + private AudioEffectsBoxData data; + public AudioEffectControlGUI[] effectControls; + + public JPanel mainPanel; + public JLabel effectsBoxLabel; + public JScrollPane scrollPane; + public JPanel effectControlsPanel; + + public AudioEffectsBoxGUI(String availableEffects) { + data = new AudioEffectsBoxData(availableEffects); + + if (availableEffects != null && !availableEffects.equals("")) { + mainPanel = new JPanel(); + effectsBoxLabel = new JLabel("Audio Effects:"); + effectControlsPanel = new JPanel(); + + if (data.getTotalEffects() > 0) { + effectControls = new AudioEffectControlGUI[data.getTotalEffects()]; + + for (int i = 0; i < effectControls.length; i++) + effectControls[i] = new AudioEffectControlGUI(data.getControlData(i)); + } else + effectControls = null; + } else + effectControls = null; + } + + public AudioEffectsBoxData getData() { + return data; + } + + public boolean hasEffects() { + return data.hasEffects(); + } + + public void show() { + mainPanel.removeAll(); + mainPanel.validate(); + + effectControlsPanel.removeAll(); + effectControlsPanel.validate(); + + GridBagLayout g = new GridBagLayout(); + GridBagConstraints c = new GridBagConstraints(); + mainPanel.setLayout(g); + + c.fill = GridBagConstraints.VERTICAL; + g.setConstraints(mainPanel, c); + + c.gridx = 0; + c.gridy = 0; + c.ipadx = 200; + c.ipady = 20; + c.fill = GridBagConstraints.CENTER; + g.setConstraints(effectsBoxLabel, c); + mainPanel.add(effectsBoxLabel); + + c.gridx = 0; + c.gridy = 1; + c.ipadx = 0; + c.ipady = 0; + g.setConstraints(effectControlsPanel, c); + mainPanel.add(effectControlsPanel); + + if (effectControls != null && effectControls.length > 0) { + effectControlsPanel.setLayout(g); + + c.gridx = 0; + c.fill = GridBagConstraints.BOTH; + + int totalShown = 0; + for (int i = 0; i < effectControls.length; i++) { + if (effectControls[i].getVisible()) { + c.gridy = totalShown; + g.setConstraints(effectControls[i].mainPanel, c); + effectControlsPanel.add(effectControls[i].mainPanel); + effectControls[i].show(); + + totalShown++; + } + } + } + + // Add the scroll pane + c.gridx = 0; + c.gridy = 1; + c.ipadx = 300; + c.ipady = 105; + scrollPane = new JScrollPane(effectControlsPanel); + scrollPane.setViewportView(effectControlsPanel); + g.setConstraints(scrollPane, c); + mainPanel.add(scrollPane); + effectControlsPanel.validate(); + mainPanel.validate(); + } +} diff --git a/marytts-client/src/main/java/marytts/client/BatchSynth.java b/marytts-client/src/main/java/marytts/client/BatchSynth.java index aac173d4..56e4b61d 100644 --- a/marytts-client/src/main/java/marytts/client/BatchSynth.java +++ b/marytts-client/src/main/java/marytts/client/BatchSynth.java @@ -17,7 +17,8 @@ * along with this program. If not, see . * */ -package marytts.client; +package marytts.client; + import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -26,105 +27,93 @@ import java.io.InputStreamReader; import java.util.StringTokenizer; import marytts.client.http.MaryHttpClient; - - - - -/** - * Copyright 2006 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. - * - * Permission is hereby granted, free of charge, to use and distribute - * this software and its documentation without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of this work, and to - * permit persons to whom this work is furnished to do so, subject to - * the following conditions: - * - * 1. The code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * 2. Any modifications must be clearly marked as such. - * 3. Original authors' names are not deleted. - * 4. The authors' names are not used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * DFKI GMBH AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DFKI GMBH NOR THE - * CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - */ - -public class BatchSynth -{ - - /** - * Generate a set of audio files from text. Example call: - * java -cp maryclient.jar -Dserver.host=localhost -Dserver.port=59125 -Dvoice=kevin16 marytts.client.BatchSynth target/dir path/to/texts.txt - * The text file must contain a target audio file name and the corresponding text in each line. - * @param args first argument, the output directory; - * the rest, file names containing text files. Each text file contains, in each line, a file name followed by the sentence to generate as a .wav file. - */ - public static void main(String[] args) throws Exception - { - File globalOutputDir = new File(args[0]); - MaryHttpClient mary = new MaryHttpClient(); - String voice = System.getProperty("voice", "us1"); - boolean haveBasename = "true".equals(System.getProperty("lines-contain-basename", "true")); // default: true, for backward compatibility - String inputFormat = "TEXT"; - String locale = System.getProperty("locale", "en_US"); - String outputFormat = System.getProperty("output.type", "AUDIO"); - String extension = outputFormat.equals("AUDIO") ? ".wav" : "." + outputFormat.toLowerCase(); - long globalStartTime = System.currentTimeMillis(); - int globalCounter = 0; - for (int i=1; i. - * - */ -package marytts.client; - -// General Java Classes -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.UnknownHostException; -import java.util.Locale; -import java.util.Set; -import java.util.Vector; - -import javax.sound.sampled.AudioFileFormat; - -import marytts.Version; -import marytts.client.http.MaryHttpClient; -import marytts.util.http.Address; - -/** - * An HTTP client implementing the MARY protocol. - * It can be used as a command line client or from within java code. - * @author Marc Schröder, oytun.turk - * @see MaryGUIClient A GUI interface to this client - * @see marytts.server.MaryServer Description of the MARY protocol - */ - -public abstract class MaryClient -{ - public static MaryClient getMaryClient() - throws IOException - { - return getMaryClient(null); - } - - /** - * The typical way to create a mary client. It will connect to the - * MARY server running at the given host and port, either as a HTTP or as a Socket server. - * This constructor reads two system properties: - *

    - *
  • mary.client.profile (=true/false) - - * determines whether profiling (timing) information is calculated;
  • - *
  • mary.client.quiet (=true/false) - - * tells the client not to print any of the normal information to stderr.
  • - *
- * @param host the host where to contact a MARY server - * @param port the socket port where to contact a MARY server - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public static MaryClient getMaryClient(Address serverAddress) - throws IOException - { - boolean profile = Boolean.getBoolean("mary.client.profile"); - boolean quiet = Boolean.getBoolean("mary.client.quiet"); - return getMaryClient(serverAddress, profile, quiet); - } - - public static MaryClient getMaryClient(Address serverAddress, boolean profile, boolean quiet) - throws IOException - { - MaryClient m = null; - try { - m = new MaryHttpClient(serverAddress, profile, quiet); - } catch (IOException ioe) { - try { - m = new MarySocketClient(serverAddress, profile, quiet); - } catch (IOException ioe2) { - IOException ioe3 = new IOException("Cannot connect either to a HTTP nor to a Socket MARY server at " - +(serverAddress != null ? serverAddress.getFullAddress() : "default location")); - ioe3.initCause(ioe2); - throw ioe3; - } - } - return m; - } - - protected MaryFormData data; - protected boolean beQuiet = false; - protected boolean doProfile = false; - - /** - * The simplest way to create a mary client. It will connect to the - * MARY server running on localhost. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - protected MaryClient() throws IOException - { - boolean profile = Boolean.getBoolean("mary.client.profile"); - boolean quiet = Boolean.getBoolean("mary.client.quiet"); - data = new MaryFormData(); // will try to get server address from system properties - initialise(profile, quiet); - } - - protected MaryClient(boolean quiet) throws IOException - { - boolean profile = Boolean.getBoolean("mary.client.profile"); - data = new MaryFormData(); // will try to get server address from system properties - - initialise(profile, quiet); - } - - /** - * The typical way to create a mary client. It will connect to the - * MARY client running at the given host and port. - * This constructor reads two system properties: - *
    - *
  • mary.client.profile (=true/false) - - * determines whether profiling (timing) information is calculated;
  • - *
  • mary.client.quiet (=true/false) - - * tells the client not to print any of the normal information to stderr.
  • - *
- * @param host the host where to contact a MARY server - * @param port the socket port where to contact a MARY server - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - protected MaryClient(Address serverAddress) throws IOException - { - boolean profile = Boolean.getBoolean("mary.client.profile"); - boolean quiet = Boolean.getBoolean("mary.client.quiet"); - if (serverAddress != null) { - data = new MaryFormData(serverAddress); - } else { - data = new MaryFormData(); // will try to get server address from system properties - } - - initialise(profile, quiet); - } - - /** - * An alternative way to create a mary client, which works with applets. - * It will connect to the MARY client running at the given host and port. - * Note that in applets, the host must be the same as the one from which - * the applet was loaded; otherwise, a security exception is thrown. - * @param host the host where to contact a MARY server - * @param port the socket port where to contact a MARY server - * @param profile determines whether profiling (timing) information is calculated - * @param quiet tells the client not to print any of the normal information to stderr - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - protected MaryClient(Address serverAddress, boolean profile, boolean quiet) throws IOException - { - if (serverAddress != null) { - data = new MaryFormData(serverAddress); - } else { - data = new MaryFormData(); // will try to get server address from system properties - } - - initialise(profile, quiet); - } - - /** - * Initialise a connection to the MARY server at the specified host and port. - * @param serverHost the host where to contact a MARY server - * @param serverPort the socket port where to contact a MARY server - * @param profile whether to do profiling - * @param quiet whether to refrain from printing information to stderr - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - protected final void initialise(boolean profile, boolean quiet) throws IOException - { - // This must work for applets too, so no system property queries here: - doProfile = profile; - beQuiet = quiet; - - String[] info; - if (!beQuiet) - System.err.println("Mary TTS client " + Version.specificationVersion() + " (impl. " + Version.implementationVersion() + ")"); - - try { - fillServerVersion(); - } catch (IOException e1) { - IOException ioe = new IOException("MARY client cannot connect to MARY server at\n"+ - data.hostAddress.getFullAddress()+"\n"+ - "Make sure that you have started the mary server\n"+ - "or specify a different host or port using \n"+ - "maryclient -Dserver.host=my.host.com -Dserver.port=12345"); - ioe.initCause(e1); - throw ioe; - } - if (data.serverVersionInfo == null || !data.serverVersionInfo.startsWith("Mary")) { - throw new IOException("This does not seem to be the expected kind of MARY server at "+data.hostAddress.getFullAddress()+"..."); - } - - if (!"unknown".equals(data.serverVersionNo) && !isServerVersionAtLeast("4.0")) { - throw new IOException("Found old MARY server (version "+data.serverVersionNo+") -- this client will only work with servers of version 4.0 or newer."); - } - - if (!beQuiet) - { - System.err.print("Connected to " + data.hostAddress.getFullAddress() + ", "); - System.err.println(data.serverVersionInfo); - - if (!data.serverCanStream) { - System.err.println("Server version " + data.serverVersionNo + " cannot stream audio, defaulting to non-streaming"); - } - } - - fillVoices(); - //Limited domain example texts - if (data.allVoices!=null && data.allVoices.size()>0) { - if (data.allVoices.elementAt(data.voiceSelected).isLimitedDomain()) { - data.limitedDomainExampleTexts = getVoiceExampleTextsLimitedDomain(data.allVoices.elementAt(data.voiceSelected).name()); - } - } - - //Input text - if (data.allVoices!=null && data.allVoices.size()>0 && data.inputDataTypes!=null && data.inputDataTypes.size()>0) { - if (data.allVoices.elementAt(data.voiceSelected).isLimitedDomain()) - data.inputText = data.limitedDomainExampleTexts.get(data.limitedDomainExampleTextSelected); - else - data.inputText = getServerExampleText(data.inputDataTypes.get(data.inputTypeSelected).name(), data.allVoices.elementAt(data.voiceSelected).getLocale().toString()); - } - } - - - - /////////////////////////////////////////////////////////////////////// - //////////////////////// Information requests ///////////////////////// - /////////////////////////////////////////////////////////////////////// - - public Address getAddress() - { - return data.hostAddress; - } - - public String getHost() - { - return data.hostAddress.getHost(); - } - - public int getPort() - { - return data.hostAddress.getPort(); - } - - - /** - * Get the audio file format types known by the server, one per line. - * Each line has the format: extension name - * @return - * @throws IOException - * @throws UnknownHostException - */ - public Vector getAudioFileFormatTypes() throws IOException - { - if (data.audioFileFormatTypes==null || data.audioOutTypes==null) { - fillAudioFileFormatAndOutTypes(); - } - return data.audioFileFormatTypes; - } - - public Vector getAudioOutTypes() throws IOException - { - if (data.audioFileFormatTypes==null || data.audioOutTypes==null) { - fillAudioFileFormatAndOutTypes(); - } - return data.audioOutTypes; - } - - protected abstract void fillAudioFileFormatAndOutTypes() throws IOException; - - protected abstract void fillServerVersion() throws IOException; - - - public boolean isServerVersionAtLeast(String version) - throws IOException - { - if (data.serverVersionNo.equals("unknown")) - fillServerVersion(); - return data.isServerVersionAtLeast(version); - } - - - - /** - * Obtain a list of all data types known to the server. If the information is not - * yet available, the server is queried. This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @throws Exception if communication with the server fails - */ - public Vector getAllDataTypes() throws IOException - { - if (data.allDataTypes == null) - fillDataTypes(); - - assert data.allDataTypes != null && data.allDataTypes.size() > 0; - - return data.allDataTypes; - } - - /** - * Obtain a list of input data types known to the server. If the information is not - * yet available, the server is queried. This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @return a Vector of MaryHttpClient.DataType objects. - * @throws Exception if communication with the server fails - */ - public Vector getInputDataTypes() throws IOException - { - if (data.inputDataTypes == null) - fillDataTypes(); - - assert data.inputDataTypes != null && data.inputDataTypes.size() > 0; - - return data.inputDataTypes; - } - - /** - * Obtain a list of output data types known to the server. If the information is not - * yet available, the server is queried. This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @return a Vector of MaryHttpClient.DataType objects. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public Vector getOutputDataTypes() throws IOException - { - if (data.outputDataTypes == null) - fillDataTypes(); - - assert data.outputDataTypes != null && data.outputDataTypes.size() > 0; - - return data.outputDataTypes; - } - - protected abstract void fillDataTypes() throws IOException; - - /** - * Provide a list of voices known to the server. If the information is not yet - * available, query the server for it. This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @return a Vector of MaryHttpClient.Voice objects. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public Vector getVoices() throws IOException - { - if (data.allVoices == null) - fillVoices(); - - assert data.allVoices != null && data.allVoices.size() > 0; - - return data.allVoices; - } - - /** - * Provide a list of voices known to the server for the given locale. - * If the information is not yet available, query the server for it. - * This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @param locale the requested voice locale - * @return a Vector of MaryHttpClient.Voice objects, or null if no voices exist for - * that locale. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public Vector getVoices(Locale locale) throws IOException - { - if (data.allVoices == null) - fillVoices(); - - return data.voicesByLocaleMap.get(locale); - } - - /** - * Provide a list of general domain voices known to the server. - * If the information is not yet available, query the server for it. - * This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public Vector getGeneralDomainVoices() throws IOException - { - Vector voices = getVoices(); - Vector requestedVoices = new Vector(); - - for (MaryClient.Voice v: voices) - { - if (!v.isLimitedDomain()) - requestedVoices.add(v); - } - - if (!requestedVoices.isEmpty()) - return requestedVoices; - else - return null; - } - - /** - * Provide a list of limited domain voices known to the server. - * If the information is not yet available, query the server for it. - * This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. - * @throws Exception if communication with the server fails - */ - public Vector getLimitedDomainVoices() throws IOException - { - Vector voices = getVoices(); - Vector requestedVoices = new Vector(); - - for (MaryClient.Voice v : voices) - { - if (v.isLimitedDomain()) - requestedVoices.add(v); - } - - if (!requestedVoices.isEmpty()) - return requestedVoices; - else - return null; - } - - /** - * Provide a list of general domain voices known to the server. - * If the information is not yet available, query the server for it. - * This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @param locale the requested voice locale - * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. - * @throws Exception if communication with the server fails - */ - public Vector getGeneralDomainVoices(Locale locale) throws IOException - { - Vector voices = getVoices(locale); - Vector requestedVoices = new Vector(); - - for (MaryClient.Voice v : voices) - { - if (!v.isLimitedDomain()) - requestedVoices.add(v); - } - - if (!requestedVoices.isEmpty()) - return requestedVoices; - else - return null; - } - - /** - * Provide a list of limited domain voices known to the server. - * If the information is not yet available, query the server for it. - * This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @param locale the requested voice locale - * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. - * @throws Exception if communication with the server fails - */ - public Vector getLimitedDomainVoices(Locale locale) throws IOException - { - Vector voices = getVoices(locale); - Vector requestedVoices = new Vector(); - for (MaryClient.Voice v : voices) - { - if (v.isLimitedDomain()) - requestedVoices.add(v); - } - - if (!requestedVoices.isEmpty()) - return requestedVoices; - else - return null; - } - - protected abstract void fillVoices() throws IOException; - - - public Set getLocales() throws IOException { - if (data.locales == null) { - fillLocales(); - } - return data.locales; - } - - protected abstract void fillLocales() throws IOException; - - /** - * Request the example texts of a limited domain - * unit selection voice from the server - * @param voicename the voice - * @return the example text - * @throws IOException - * @throws UnknownHostException - */ - public Vector getVoiceExampleTextsLimitedDomain(String voicename) throws IOException - { - if (!data.voiceExampleTextsLimitedDomain.containsKey(voicename)) { - fillVoiceExampleTexts(voicename); - } - return data.voiceExampleTextsLimitedDomain.get(voicename); - } - - protected abstract void fillVoiceExampleTexts(String voicename) throws IOException; - - /** - * Request an example text for a given data type from the server. - * @param dataType the string representation of the data type, - * e.g. "RAWMARYXML". This is optional information - * which is not required for the normal operation of the client, but - * may help to avoid incompatibilities. - * @return the example text, or null if none could be obtained. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public String getServerExampleText(String dataType, String locale) throws IOException - { - if (!data.serverExampleTexts.containsKey(dataType+" "+locale)) - { - fillServerExampleText(dataType, locale); - } - - data.currentExampleText = data.serverExampleTexts.get(dataType+" "+locale); - - return data.currentExampleText; - } - - protected abstract void fillServerExampleText(String dataType, String locale) throws IOException; - - /** - * Request the available audio effects for a voice from the server - * @param voicename the voice - * @return A string of available audio effects and default parameters, i.e. "FIRFilter,Robot(amount=50)" - * @throws IOException - * @throws UnknownHostException - */ - protected abstract String getDefaultAudioEffects() throws IOException; - - public String getAudioEffects() throws IOException - { - if (data.audioEffects==null) - data.audioEffects = getDefaultAudioEffects(); - - return data.audioEffects; - } - - - public abstract String requestDefaultEffectParameters(String effectName) throws IOException; - - public abstract String requestFullEffect(String effectName, String currentEffectParameters) throws IOException; - - public abstract boolean isHMMEffect(String effectName) throws IOException; - - - public String requestEffectHelpText(String effectName) throws IOException - { - if (!data.audioEffectHelpTextsMap.containsKey(effectName)) { - fillEffectHelpText(effectName); - } - return data.audioEffectHelpTextsMap.get(effectName); - } - - protected abstract void fillEffectHelpText(String effectName) throws IOException; - - - - public abstract String getFeatures(String locale) throws IOException; - - public abstract String getFeaturesForVoice(String voice) throws IOException; - - - - /////////////////////////////////////////////////////////////////////// - //////////////////////// Actual synthesis requests //////////////////// - /////////////////////////////////////////////////////////////////////// - - - /** - * Call the mary client to stream audio via the given audio player. The server will - * provide audio data as it is being generated. If the connection to the server is - * not too slow, streaming will be attractive because it reduces considerably the - * amount of time one needs to wait for the first audio to play. - * @param input a textual representation of the input data - * @param inputType the name of the input data type, e.g. TEXT or RAWMARYXML. - * @param audioType the name of the audio format, e.g. "WAVE" or "MP3". - * @param defaultVoiceName the name of the voice to use, e.g. de7 or us1. - * @param audioPlayer the FreeTTS audio player with which to play the synthesised audio data. The - * given audio player must already be instanciated. See the package - * com.sun.speech.freetts.audio in FreeTTS for implementations of AudioPlayer. - * @param listener a means for letting calling code know that the AudioPlayer has finished. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - * @see #getInputDataTypes() - * @see #getVoices() - */ - public void streamAudio(String input, String inputType, String locale, String audioType, String defaultVoiceName, String defaultStyle, String defaultEffects, marytts.util.data.audio.AudioPlayer audioPlayer, AudioPlayerListener listener) - throws IOException - { - _process(input, inputType, "AUDIO", locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, audioPlayer, 0, true, null, listener); - } - - /** - * The standard way to call the MARY client when the output is to - * go to an output stream. - * @param input a textual representation of the input data - * @param inputType the name of the input data type, e.g. TEXT or RAWMARYXML. - * @param outputType the name of the output data type, e.g. AUDIO or ACOUSTPARAMS. - * @param audioType the name of the audio format, e.g. "WAVE" or "MP3". - * @param defaultVoiceName the name of the voice to use, e.g. de7 or us1. - * @param audioEffects the audio effects and their parameters to be applied as a post-processing step, e.g. Robot(Amount=100), Whisper(amount=50) - * @param outputTypeParams any additional parameters, e.g. for output type TARGETFEATURES, the space-separated list of features to produce. Can be null. - * @param output the output stream into which the data from the server is to be written. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - * @see #getInputDataTypes() - * @see #getOutputDataTypes() - * @see #getVoices() - */ - public void process(String input, String inputType, String outputType, String locale, - String audioType, String defaultVoiceName, String defaultStyle, String defaultEffects, String outputTypeParams, OutputStream output) - throws IOException - { - _process(input, inputType, outputType, locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, output, 0, false, outputTypeParams, null); - } - - public void process(String input, String inputType, String outputType, String locale, - String audioType, String defaultVoiceName, OutputStream output) - throws IOException - { - process( input, inputType, outputType, locale, audioType, defaultVoiceName, "", null, null, output); - } - - /** - * An alternative way to call the MARY client when the output is to - * go to an output stream, with a timeout. - * @param input a textual representation of the input data - * @param inputType the name of the input data type, e.g. TEXT or RAWMARYXML. - * @param outputType the name of the output data type, e.g. AUDIO or ACOUSTPARAMS. - * @param audioType the name of the audio format, e.g. "WAVE" or "MP3". - * @param defaultVoiceName the name of the voice to use, e.g. de7 or us1. - * @param audioEffects the audio effects and their parameters to be applied as a post-processing step, e.g. Robot(Amount=100), Whisper(amount=50) - * @param outputTypeParams any additional parameters, e.g. for output type TARGETFEATURES, the space-separated list of features to produce. Can be null. - * @param output the output stream into which the data from the server is to be written. - * @param timeout if >0, sets a timer to as many milliseconds; if processing is not finished by then, - * the connection with the Mary server is forcefully cut, resulting in an IOException. - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - * @see #getInputDataTypes() - * @see #getOutputDataTypes() - * @see #getVoices() - */ - public void process(String input, String inputType, String outputType, String locale, - String audioType, String defaultVoiceName, String defaultStyle, String defaultEffects, String outputTypeParams, - OutputStream output, long timeout) - throws IOException - { - _process(input, inputType, outputType, locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, output, timeout, false, outputTypeParams, null); - } - - public void process(String input, String inputType, String outputType, String locale, - String audioType, String defaultVoiceName, OutputStream output, long timeout) - throws IOException - { - process(input, inputType, outputType, locale, audioType, defaultVoiceName, "", null, null, output, timeout); - } - - protected abstract void _process(String input, String inputType, String outputType, String locale, String audioType, - String defaultVoiceName, String defaultStyle, String defaultEffects, - Object output, long timeout, boolean streamingAudio, String outputTypeParams, AudioPlayerListener playerListener) - throws IOException; - - - - - - - - /** - * Return an audio file format type for the given string. - * In addition to the built-in types, this can deal with MP3 - * supported by tritonus. - * @return the audio file format type if it is known, or null. - * @see #canCreateMP3() - * @see #canCreateOgg() - */ - public static AudioFileFormat.Type getAudioFileFormatType(String name) - { - AudioFileFormat.Type at; - if (name.equals("MP3")) - { - // Supported by tritonus plugin - at = new AudioFileFormat.Type("MP3", "mp3"); - } - else if (name.equals("Vorbis")) - { - // supported by tritonus plugin - at = new AudioFileFormat.Type("Vorbis", "ogg"); - } - else - { - try { - at = (AudioFileFormat.Type) AudioFileFormat.Type.class.getField(name).get(null); - } catch (Exception e) { - return null; - } - } - - return at; - } - /** - * An abstraction of server info about available voices. - * @author Marc Schröder - * - * - */ - public static class Voice - { - private String name; - private Locale locale; - private String gender; - private String domain; - private String synthesizerType; - - private boolean isLimitedDomain; - public Voice(String name, Locale locale, String gender, String domain) - { - this.name = name; - this.locale = locale; - this.gender = gender; - this.domain = domain; - if (domain == null || domain.equals("general")){ - isLimitedDomain = false;} - else {isLimitedDomain = true;} - - this.synthesizerType = "not-specified"; - } - public Locale getLocale() { return locale; } - public String name() { return name; } - public String gender() { return gender; } - public String synthesizerType() {return synthesizerType;} - public void setSynthesizerType(String synthesizerTypeIn) {synthesizerType = synthesizerTypeIn;} - public String toString() { return name + " (" + locale.getDisplayLanguage() + ", " + gender - + (isLimitedDomain ? ", " + domain : "") +")";} - public boolean isLimitedDomain() { return isLimitedDomain; } - public boolean isHMMVoice() { - return synthesizerType.compareToIgnoreCase("hmm")==0; - } - } - - - /** - * An abstraction of server info about available data types. - * @author Marc Schröder - * - * - */ - public static class DataType - { - private String name; - private boolean isInputType; - private boolean isOutputType; - public DataType(String name, boolean isInputType, boolean isOutputType) { - this.name = name; - this.isInputType = isInputType; - this.isOutputType = isOutputType; - } - public String name() { return name; } - public boolean isInputType() { return isInputType; } - public boolean isOutputType() { return isOutputType; } - public boolean isTextType() { return !name.equals("AUDIO"); } - public String toString() { return name; } - } - - /** - * A means of letting a caller code know - * that the audioplayer has finished. - * @author Marc Schröder - * - */ - public static interface AudioPlayerListener - { - /** - * Notify the listener that the audio player has finished. - * - */ - public void playerFinished(); - - /** - * Inform the listener that the audio player has thrown an exception. - * @param e the exception thrown - */ - public void playerException(Exception e); - } - - public static class WarningReader extends Thread - { - protected BufferedReader in; - protected StringBuffer warnings; - public WarningReader(BufferedReader in) - { - this.in = in; - warnings = new StringBuffer(); - } - - public String getWarnings() { return warnings.toString(); } - - public void run() - { - char[] cbuf = new char[1024]; - int nr; - try { - while ((nr = in.read(cbuf)) != -1) { - // warnings from the server - warnings.append(cbuf, 0, nr); - } - } catch (IOException ioe) { - } - } - } - - - public static void usage() - { - System.err.println("usage:"); - System.err.println("java [properties] " + MaryHttpClient.class.getName() + " [inputfile]"); - System.err.println(); - System.err.println("Properties are: -Dinput.type=INPUTTYPE"); - System.err.println(" -Doutput.type=OUTPUTTYPE"); - System.err.println(" -Dlocale=LOCALE"); - System.err.println(" -Daudio.type=AUDIOTYPE"); - System.err.println(" -Dvoice.default=male|female|de1|de2|de3|..."); - System.err.println(" -Dserver.host=HOSTNAME"); - System.err.println(" -Dserver.port=PORTNUMBER"); - System.err.println( - "where INPUTTYPE is one of TEXT, RAWMARYXML, TOKENS, WORDS, POS,"); - System.err.println( - " PHONEMES, INTONATION, ALLOPHONES, ACOUSTPARAMS or MBROLA,"); - System.err.println(" OUTPUTTYPE is one of TOKENS, WORDS, POS, PHONEMES,"); - System.err.println(" INTONATION, ALLOPHONES, ACOUSTPARAMS, MBROLA, or AUDIO,"); - System.err.println(" LOCALE is the language and/or the country (e.g., de, en_US);"); - System.err.println("and AUDIOTYPE is one of AIFF, AU, WAVE, MP3, and Vorbis."); - System.err.println("The default values for input.type and output.type are TEXT and AUDIO,"); - System.err.println("respectively; default locale is en_US; the default audio.type is WAVE."); - System.err.println(); - System.err.println("inputfile must be of type input.type."); - System.err.println("If no inputfile is given, the program will read from standard input."); - System.err.println(); - System.err.println("The output is written to standard output, so redirect or pipe as appropriate."); - } - - public static void main(String[] args) throws IOException, InterruptedException - { - if (args.length > 0 && args[0].equals("-h")) - { - usage(); - System.exit(1); - } - - MaryClient mc = getMaryClient(); - BufferedReader inputReader = null; - // read requested input/output type from properties: - String inputType = System.getProperty("input.type", "TEXT"); - String outputType = System.getProperty("output.type", "AUDIO"); - String locale = System.getProperty("locale", "en_US"); - String audioType = System.getProperty("audio.type", "WAVE"); - if (!(audioType.equals("AIFC") - || audioType.equals("AIFF") - || audioType.equals("AU") - || audioType.equals("SND") - || audioType.equals("WAVE") - || audioType.equals("MP3") - || audioType.equals("Vorbis"))) { - System.err.println("Invalid value '" + audioType + "' for property 'audio.type'"); - System.err.println(); - usage(); - System.exit(1); - } - String defaultVoiceName = System.getProperty("voice.default"); - String defaultStyle = ""; - String defaultEffects = null; - String outputTypeParams = System.getProperty("output.type.params"); // null if not present - - if (args.length > 0) { - File file = new File(args[0]); - inputReader = new BufferedReader(new FileReader(file)); - } else { // no Filename, read from stdin: - inputReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); - } - - // Read input into a string: - StringBuilder sb = new StringBuilder(1024); - char[] buf = new char[1024]; - int nr; - while ((nr = inputReader.read(buf)) != -1) { - sb.append(buf, 0, nr); - } - - try { - mc.process(sb.toString(), inputType, outputType, locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, outputTypeParams, System.out); - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - } - - -} - +/** + * Copyright 2000-2009 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. + * + * This file is part of MARY TTS. + * + * MARY TTS is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + */ +package marytts.client; + +// General Java Classes +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.UnknownHostException; +import java.util.Locale; +import java.util.Set; +import java.util.Vector; + +import javax.sound.sampled.AudioFileFormat; + +import marytts.Version; +import marytts.client.http.MaryHttpClient; +import marytts.util.http.Address; + +/** + * An HTTP client implementing the MARY protocol. + * It can be used as a command line client or from within java code. + * @author Marc Schröder, oytun.turk + * @see MaryGUIClient A GUI interface to this client + * @see marytts.server.MaryServer Description of the MARY protocol + */ + +public abstract class MaryClient +{ + public static MaryClient getMaryClient() + throws IOException + { + return getMaryClient(null); + } + + /** + * The typical way to create a mary client. It will connect to the + * MARY server running at the given host and port, either as a HTTP or as a Socket server. + * This constructor reads two system properties: + *
    + *
  • mary.client.profile (=true/false) - + * determines whether profiling (timing) information is calculated;
  • + *
  • mary.client.quiet (=true/false) - + * tells the client not to print any of the normal information to stderr.
  • + *
+ * @param host the host where to contact a MARY server + * @param port the socket port where to contact a MARY server + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public static MaryClient getMaryClient(Address serverAddress) + throws IOException + { + boolean profile = Boolean.getBoolean("mary.client.profile"); + boolean quiet = Boolean.getBoolean("mary.client.quiet"); + return getMaryClient(serverAddress, profile, quiet); + } + + public static MaryClient getMaryClient(Address serverAddress, boolean profile, boolean quiet) + throws IOException + { + MaryClient m = null; + try { + m = new MaryHttpClient(serverAddress, profile, quiet); + } catch (IOException ioe) { + try { + m = new MarySocketClient(serverAddress, profile, quiet); + } catch (IOException ioe2) { + IOException ioe3 = new IOException("Cannot connect either to a HTTP nor to a Socket MARY server at " + +(serverAddress != null ? serverAddress.getFullAddress() : "default location")); + ioe3.initCause(ioe2); + throw ioe3; + } + } + return m; + } + + protected MaryFormData data; + protected boolean beQuiet = false; + protected boolean doProfile = false; + + /** + * The simplest way to create a mary client. It will connect to the + * MARY server running on localhost. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + protected MaryClient() throws IOException + { + boolean profile = Boolean.getBoolean("mary.client.profile"); + boolean quiet = Boolean.getBoolean("mary.client.quiet"); + data = new MaryFormData(); // will try to get server address from system properties + initialise(profile, quiet); + } + + protected MaryClient(boolean quiet) throws IOException + { + boolean profile = Boolean.getBoolean("mary.client.profile"); + data = new MaryFormData(); // will try to get server address from system properties + + initialise(profile, quiet); + } + + /** + * The typical way to create a mary client. It will connect to the + * MARY client running at the given host and port. + * This constructor reads two system properties: + *
    + *
  • mary.client.profile (=true/false) - + * determines whether profiling (timing) information is calculated;
  • + *
  • mary.client.quiet (=true/false) - + * tells the client not to print any of the normal information to stderr.
  • + *
+ * @param host the host where to contact a MARY server + * @param port the socket port where to contact a MARY server + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + protected MaryClient(Address serverAddress) throws IOException + { + boolean profile = Boolean.getBoolean("mary.client.profile"); + boolean quiet = Boolean.getBoolean("mary.client.quiet"); + if (serverAddress != null) { + data = new MaryFormData(serverAddress); + } else { + data = new MaryFormData(); // will try to get server address from system properties + } + + initialise(profile, quiet); + } + + /** + * An alternative way to create a mary client, which works with applets. + * It will connect to the MARY client running at the given host and port. + * Note that in applets, the host must be the same as the one from which + * the applet was loaded; otherwise, a security exception is thrown. + * @param host the host where to contact a MARY server + * @param port the socket port where to contact a MARY server + * @param profile determines whether profiling (timing) information is calculated + * @param quiet tells the client not to print any of the normal information to stderr + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + protected MaryClient(Address serverAddress, boolean profile, boolean quiet) throws IOException + { + if (serverAddress != null) { + data = new MaryFormData(serverAddress); + } else { + data = new MaryFormData(); // will try to get server address from system properties + } + + initialise(profile, quiet); + } + + /** + * Initialise a connection to the MARY server at the specified host and port. + * @param serverHost the host where to contact a MARY server + * @param serverPort the socket port where to contact a MARY server + * @param profile whether to do profiling + * @param quiet whether to refrain from printing information to stderr + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + protected final void initialise(boolean profile, boolean quiet) throws IOException + { + // This must work for applets too, so no system property queries here: + doProfile = profile; + beQuiet = quiet; + + String[] info; + if (!beQuiet) + System.err.println("Mary TTS client " + Version.specificationVersion() + " (impl. " + Version.implementationVersion() + ")"); + + try { + fillServerVersion(); + } catch (IOException e1) { + IOException ioe = new IOException("MARY client cannot connect to MARY server at\n"+ + data.hostAddress.getFullAddress()+"\n"+ + "Make sure that you have started the mary server\n"+ + "or specify a different host or port using \n"+ + "maryclient -Dserver.host=my.host.com -Dserver.port=12345"); + ioe.initCause(e1); + throw ioe; + } + if (data.serverVersionInfo == null || !data.serverVersionInfo.startsWith("Mary")) { + throw new IOException("This does not seem to be the expected kind of MARY server at "+data.hostAddress.getFullAddress()+"..."); + } + + if (!"unknown".equals(data.serverVersionNo) && !isServerVersionAtLeast("4.0")) { + throw new IOException("Found old MARY server (version "+data.serverVersionNo+") -- this client will only work with servers of version 4.0 or newer."); + } + + if (!beQuiet) + { + System.err.print("Connected to " + data.hostAddress.getFullAddress() + ", "); + System.err.println(data.serverVersionInfo); + + if (!data.serverCanStream) { + System.err.println("Server version " + data.serverVersionNo + " cannot stream audio, defaulting to non-streaming"); + } + } + + fillVoices(); + //Limited domain example texts + if (data.allVoices!=null && data.allVoices.size()>0) { + if (data.allVoices.elementAt(data.voiceSelected).isLimitedDomain()) { + data.limitedDomainExampleTexts = getVoiceExampleTextsLimitedDomain(data.allVoices.elementAt(data.voiceSelected).name()); + } + } + + //Input text + if (data.allVoices!=null && data.allVoices.size()>0 && data.inputDataTypes!=null && data.inputDataTypes.size()>0) { + if (data.allVoices.elementAt(data.voiceSelected).isLimitedDomain()) + data.inputText = data.limitedDomainExampleTexts.get(data.limitedDomainExampleTextSelected); + else + data.inputText = getServerExampleText(data.inputDataTypes.get(data.inputTypeSelected).name(), data.allVoices.elementAt(data.voiceSelected).getLocale().toString()); + } + } + + + + /////////////////////////////////////////////////////////////////////// + //////////////////////// Information requests ///////////////////////// + /////////////////////////////////////////////////////////////////////// + + public Address getAddress() + { + return data.hostAddress; + } + + public String getHost() + { + return data.hostAddress.getHost(); + } + + public int getPort() + { + return data.hostAddress.getPort(); + } + + + /** + * Get the audio file format types known by the server, one per line. + * Each line has the format: extension name + * @return + * @throws IOException + * @throws UnknownHostException + */ + public Vector getAudioFileFormatTypes() throws IOException + { + if (data.audioFileFormatTypes==null || data.audioOutTypes==null) { + fillAudioFileFormatAndOutTypes(); + } + return data.audioFileFormatTypes; + } + + public Vector getAudioOutTypes() throws IOException + { + if (data.audioFileFormatTypes==null || data.audioOutTypes==null) { + fillAudioFileFormatAndOutTypes(); + } + return data.audioOutTypes; + } + + protected abstract void fillAudioFileFormatAndOutTypes() throws IOException; + + protected abstract void fillServerVersion() throws IOException; + + + public boolean isServerVersionAtLeast(String version) + throws IOException + { + if (data.serverVersionNo.equals("unknown")) + fillServerVersion(); + return data.isServerVersionAtLeast(version); + } + + + + /** + * Obtain a list of all data types known to the server. If the information is not + * yet available, the server is queried. This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @throws Exception if communication with the server fails + */ + public Vector getAllDataTypes() throws IOException + { + if (data.allDataTypes == null) + fillDataTypes(); + + assert data.allDataTypes != null && data.allDataTypes.size() > 0; + + return data.allDataTypes; + } + + /** + * Obtain a list of input data types known to the server. If the information is not + * yet available, the server is queried. This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @return a Vector of MaryHttpClient.DataType objects. + * @throws Exception if communication with the server fails + */ + public Vector getInputDataTypes() throws IOException + { + if (data.inputDataTypes == null) + fillDataTypes(); + + assert data.inputDataTypes != null && data.inputDataTypes.size() > 0; + + return data.inputDataTypes; + } + + /** + * Obtain a list of output data types known to the server. If the information is not + * yet available, the server is queried. This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @return a Vector of MaryHttpClient.DataType objects. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public Vector getOutputDataTypes() throws IOException + { + if (data.outputDataTypes == null) + fillDataTypes(); + + assert data.outputDataTypes != null && data.outputDataTypes.size() > 0; + + return data.outputDataTypes; + } + + protected abstract void fillDataTypes() throws IOException; + + /** + * Provide a list of voices known to the server. If the information is not yet + * available, query the server for it. This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @return a Vector of MaryHttpClient.Voice objects. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public Vector getVoices() throws IOException + { + if (data.allVoices == null) + fillVoices(); + + assert data.allVoices != null && data.allVoices.size() > 0; + + return data.allVoices; + } + + /** + * Provide a list of voices known to the server for the given locale. + * If the information is not yet available, query the server for it. + * This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @param locale the requested voice locale + * @return a Vector of MaryHttpClient.Voice objects, or null if no voices exist for + * that locale. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public Vector getVoices(Locale locale) throws IOException + { + if (data.allVoices == null) + fillVoices(); + + return data.voicesByLocaleMap.get(locale); + } + + /** + * Provide a list of general domain voices known to the server. + * If the information is not yet available, query the server for it. + * This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public Vector getGeneralDomainVoices() throws IOException + { + Vector voices = getVoices(); + Vector requestedVoices = new Vector(); + + for (MaryClient.Voice v: voices) + { + if (!v.isLimitedDomain()) + requestedVoices.add(v); + } + + if (!requestedVoices.isEmpty()) + return requestedVoices; + else + return null; + } + + /** + * Provide a list of limited domain voices known to the server. + * If the information is not yet available, query the server for it. + * This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. + * @throws Exception if communication with the server fails + */ + public Vector getLimitedDomainVoices() throws IOException + { + Vector voices = getVoices(); + Vector requestedVoices = new Vector(); + + for (MaryClient.Voice v : voices) + { + if (v.isLimitedDomain()) + requestedVoices.add(v); + } + + if (!requestedVoices.isEmpty()) + return requestedVoices; + else + return null; + } + + /** + * Provide a list of general domain voices known to the server. + * If the information is not yet available, query the server for it. + * This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @param locale the requested voice locale + * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. + * @throws Exception if communication with the server fails + */ + public Vector getGeneralDomainVoices(Locale locale) throws IOException + { + Vector voices = getVoices(locale); + Vector requestedVoices = new Vector(); + + for (MaryClient.Voice v : voices) + { + if (!v.isLimitedDomain()) + requestedVoices.add(v); + } + + if (!requestedVoices.isEmpty()) + return requestedVoices; + else + return null; + } + + /** + * Provide a list of limited domain voices known to the server. + * If the information is not yet available, query the server for it. + * This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @param locale the requested voice locale + * @return a Vector of MaryHttpClient.Voice objects, or null if no such voices exist. + * @throws Exception if communication with the server fails + */ + public Vector getLimitedDomainVoices(Locale locale) throws IOException + { + Vector voices = getVoices(locale); + Vector requestedVoices = new Vector(); + for (MaryClient.Voice v : voices) + { + if (v.isLimitedDomain()) + requestedVoices.add(v); + } + + if (!requestedVoices.isEmpty()) + return requestedVoices; + else + return null; + } + + protected abstract void fillVoices() throws IOException; + + + public Set getLocales() throws IOException { + if (data.locales == null) { + fillLocales(); + } + return data.locales; + } + + protected abstract void fillLocales() throws IOException; + + /** + * Request the example texts of a limited domain + * unit selection voice from the server + * @param voicename the voice + * @return the example text + * @throws IOException + * @throws UnknownHostException + */ + public Vector getVoiceExampleTextsLimitedDomain(String voicename) throws IOException + { + if (!data.voiceExampleTextsLimitedDomain.containsKey(voicename)) { + fillVoiceExampleTexts(voicename); + } + return data.voiceExampleTextsLimitedDomain.get(voicename); + } + + protected abstract void fillVoiceExampleTexts(String voicename) throws IOException; + + /** + * Request an example text for a given data type from the server. + * @param dataType the string representation of the data type, + * e.g. "RAWMARYXML". This is optional information + * which is not required for the normal operation of the client, but + * may help to avoid incompatibilities. + * @return the example text, or null if none could be obtained. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public String getServerExampleText(String dataType, String locale) throws IOException + { + if (!data.serverExampleTexts.containsKey(dataType+" "+locale)) + { + fillServerExampleText(dataType, locale); + } + + data.currentExampleText = data.serverExampleTexts.get(dataType+" "+locale); + + return data.currentExampleText; + } + + protected abstract void fillServerExampleText(String dataType, String locale) throws IOException; + + /** + * Request the available audio effects for a voice from the server + * @param voicename the voice + * @return A string of available audio effects and default parameters, i.e. "FIRFilter,Robot(amount=50)" + * @throws IOException + * @throws UnknownHostException + */ + protected abstract String getDefaultAudioEffects() throws IOException; + + public String getAudioEffects() throws IOException + { + if (data.audioEffects==null) + data.audioEffects = getDefaultAudioEffects(); + + return data.audioEffects; + } + + + public abstract String requestDefaultEffectParameters(String effectName) throws IOException; + + public abstract String requestFullEffect(String effectName, String currentEffectParameters) throws IOException; + + public abstract boolean isHMMEffect(String effectName) throws IOException; + + + public String requestEffectHelpText(String effectName) throws IOException + { + if (!data.audioEffectHelpTextsMap.containsKey(effectName)) { + fillEffectHelpText(effectName); + } + return data.audioEffectHelpTextsMap.get(effectName); + } + + protected abstract void fillEffectHelpText(String effectName) throws IOException; + + + + public abstract String getFeatures(String locale) throws IOException; + + public abstract String getFeaturesForVoice(String voice) throws IOException; + + + + /////////////////////////////////////////////////////////////////////// + //////////////////////// Actual synthesis requests //////////////////// + /////////////////////////////////////////////////////////////////////// + + + /** + * Call the mary client to stream audio via the given audio player. The server will + * provide audio data as it is being generated. If the connection to the server is + * not too slow, streaming will be attractive because it reduces considerably the + * amount of time one needs to wait for the first audio to play. + * @param input a textual representation of the input data + * @param inputType the name of the input data type, e.g. TEXT or RAWMARYXML. + * @param audioType the name of the audio format, e.g. "WAVE" or "MP3". + * @param defaultVoiceName the name of the voice to use, e.g. de7 or us1. + * @param audioPlayer the FreeTTS audio player with which to play the synthesised audio data. The + * given audio player must already be instanciated. See the package + * com.sun.speech.freetts.audio in FreeTTS for implementations of AudioPlayer. + * @param listener a means for letting calling code know that the AudioPlayer has finished. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + * @see #getInputDataTypes() + * @see #getVoices() + */ + public void streamAudio(String input, String inputType, String locale, String audioType, String defaultVoiceName, String defaultStyle, String defaultEffects, marytts.util.data.audio.AudioPlayer audioPlayer, AudioPlayerListener listener) + throws IOException + { + _process(input, inputType, "AUDIO", locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, audioPlayer, 0, true, null, listener); + } + + /** + * The standard way to call the MARY client when the output is to + * go to an output stream. + * @param input a textual representation of the input data + * @param inputType the name of the input data type, e.g. TEXT or RAWMARYXML. + * @param outputType the name of the output data type, e.g. AUDIO or ACOUSTPARAMS. + * @param audioType the name of the audio format, e.g. "WAVE" or "MP3". + * @param defaultVoiceName the name of the voice to use, e.g. de7 or us1. + * @param audioEffects the audio effects and their parameters to be applied as a post-processing step, e.g. Robot(Amount=100), Whisper(amount=50) + * @param outputTypeParams any additional parameters, e.g. for output type TARGETFEATURES, the space-separated list of features to produce. Can be null. + * @param output the output stream into which the data from the server is to be written. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + * @see #getInputDataTypes() + * @see #getOutputDataTypes() + * @see #getVoices() + */ + public void process(String input, String inputType, String outputType, String locale, + String audioType, String defaultVoiceName, String defaultStyle, String defaultEffects, String outputTypeParams, OutputStream output) + throws IOException + { + _process(input, inputType, outputType, locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, output, 0, false, outputTypeParams, null); + } + + public void process(String input, String inputType, String outputType, String locale, + String audioType, String defaultVoiceName, OutputStream output) + throws IOException + { + process( input, inputType, outputType, locale, audioType, defaultVoiceName, "", null, null, output); + } + + /** + * An alternative way to call the MARY client when the output is to + * go to an output stream, with a timeout. + * @param input a textual representation of the input data + * @param inputType the name of the input data type, e.g. TEXT or RAWMARYXML. + * @param outputType the name of the output data type, e.g. AUDIO or ACOUSTPARAMS. + * @param audioType the name of the audio format, e.g. "WAVE" or "MP3". + * @param defaultVoiceName the name of the voice to use, e.g. de7 or us1. + * @param audioEffects the audio effects and their parameters to be applied as a post-processing step, e.g. Robot(Amount=100), Whisper(amount=50) + * @param outputTypeParams any additional parameters, e.g. for output type TARGETFEATURES, the space-separated list of features to produce. Can be null. + * @param output the output stream into which the data from the server is to be written. + * @param timeout if >0, sets a timer to as many milliseconds; if processing is not finished by then, + * the connection with the Mary server is forcefully cut, resulting in an IOException. + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + * @see #getInputDataTypes() + * @see #getOutputDataTypes() + * @see #getVoices() + */ + public void process(String input, String inputType, String outputType, String locale, + String audioType, String defaultVoiceName, String defaultStyle, String defaultEffects, String outputTypeParams, + OutputStream output, long timeout) + throws IOException + { + _process(input, inputType, outputType, locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, output, timeout, false, outputTypeParams, null); + } + + public void process(String input, String inputType, String outputType, String locale, + String audioType, String defaultVoiceName, OutputStream output, long timeout) + throws IOException + { + process(input, inputType, outputType, locale, audioType, defaultVoiceName, "", null, null, output, timeout); + } + + protected abstract void _process(String input, String inputType, String outputType, String locale, String audioType, + String defaultVoiceName, String defaultStyle, String defaultEffects, + Object output, long timeout, boolean streamingAudio, String outputTypeParams, AudioPlayerListener playerListener) + throws IOException; + + + + + + + + /** + * Return an audio file format type for the given string. + * In addition to the built-in types, this can deal with MP3 + * supported by tritonus. + * @return the audio file format type if it is known, or null. + * @see #canCreateMP3() + * @see #canCreateOgg() + */ + public static AudioFileFormat.Type getAudioFileFormatType(String name) + { + AudioFileFormat.Type at; + if (name.equals("MP3")) + { + // Supported by tritonus plugin + at = new AudioFileFormat.Type("MP3", "mp3"); + } + else if (name.equals("Vorbis")) + { + // supported by tritonus plugin + at = new AudioFileFormat.Type("Vorbis", "ogg"); + } + else + { + try { + at = (AudioFileFormat.Type) AudioFileFormat.Type.class.getField(name).get(null); + } catch (Exception e) { + return null; + } + } + + return at; + } + /** + * An abstraction of server info about available voices. + * @author Marc Schröder + * + * + */ + public static class Voice + { + private String name; + private Locale locale; + private String gender; + private String domain; + private String synthesizerType; + + private boolean isLimitedDomain; + public Voice(String name, Locale locale, String gender, String domain) + { + this.name = name; + this.locale = locale; + this.gender = gender; + this.domain = domain; + if (domain == null || domain.equals("general")){ + isLimitedDomain = false;} + else {isLimitedDomain = true;} + + this.synthesizerType = "not-specified"; + } + public Locale getLocale() { return locale; } + public String name() { return name; } + public String gender() { return gender; } + public String synthesizerType() {return synthesizerType;} + public void setSynthesizerType(String synthesizerTypeIn) {synthesizerType = synthesizerTypeIn;} + public String toString() { return name + " (" + locale.getDisplayLanguage() + ", " + gender + + (isLimitedDomain ? ", " + domain : "") +")";} + public boolean isLimitedDomain() { return isLimitedDomain; } + public boolean isHMMVoice() { + return synthesizerType.compareToIgnoreCase("hmm")==0; + } + } + + + /** + * An abstraction of server info about available data types. + * @author Marc Schröder + * + * + */ + public static class DataType + { + private String name; + private boolean isInputType; + private boolean isOutputType; + public DataType(String name, boolean isInputType, boolean isOutputType) { + this.name = name; + this.isInputType = isInputType; + this.isOutputType = isOutputType; + } + public String name() { return name; } + public boolean isInputType() { return isInputType; } + public boolean isOutputType() { return isOutputType; } + public boolean isTextType() { return !name.equals("AUDIO"); } + public String toString() { return name; } + } + + /** + * A means of letting a caller code know + * that the audioplayer has finished. + * @author Marc Schröder + * + */ + public static interface AudioPlayerListener + { + /** + * Notify the listener that the audio player has finished. + * + */ + public void playerFinished(); + + /** + * Inform the listener that the audio player has thrown an exception. + * @param e the exception thrown + */ + public void playerException(Exception e); + } + + public static class WarningReader extends Thread + { + protected BufferedReader in; + protected StringBuffer warnings; + public WarningReader(BufferedReader in) + { + this.in = in; + warnings = new StringBuffer(); + } + + public String getWarnings() { return warnings.toString(); } + + public void run() + { + char[] cbuf = new char[1024]; + int nr; + try { + while ((nr = in.read(cbuf)) != -1) { + // warnings from the server + warnings.append(cbuf, 0, nr); + } + } catch (IOException ioe) { + } + } + } + + + public static void usage() + { + System.err.println("usage:"); + System.err.println("java [properties] " + MaryHttpClient.class.getName() + " [inputfile]"); + System.err.println(); + System.err.println("Properties are: -Dinput.type=INPUTTYPE"); + System.err.println(" -Doutput.type=OUTPUTTYPE"); + System.err.println(" -Dlocale=LOCALE"); + System.err.println(" -Daudio.type=AUDIOTYPE"); + System.err.println(" -Dvoice.default=male|female|de1|de2|de3|..."); + System.err.println(" -Dserver.host=HOSTNAME"); + System.err.println(" -Dserver.port=PORTNUMBER"); + System.err.println( + "where INPUTTYPE is one of TEXT, RAWMARYXML, TOKENS, WORDS, POS,"); + System.err.println( + " PHONEMES, INTONATION, ALLOPHONES, ACOUSTPARAMS or MBROLA,"); + System.err.println(" OUTPUTTYPE is one of TOKENS, WORDS, POS, PHONEMES,"); + System.err.println(" INTONATION, ALLOPHONES, ACOUSTPARAMS, MBROLA, or AUDIO,"); + System.err.println(" LOCALE is the language and/or the country (e.g., de, en_US);"); + System.err.println("and AUDIOTYPE is one of AIFF, AU, WAVE, MP3, and Vorbis."); + System.err.println("The default values for input.type and output.type are TEXT and AUDIO,"); + System.err.println("respectively; default locale is en_US; the default audio.type is WAVE."); + System.err.println(); + System.err.println("inputfile must be of type input.type."); + System.err.println("If no inputfile is given, the program will read from standard input."); + System.err.println(); + System.err.println("The output is written to standard output, so redirect or pipe as appropriate."); + } + + public static void main(String[] args) throws IOException, InterruptedException + { + if (args.length > 0 && args[0].equals("-h")) + { + usage(); + System.exit(1); + } + + MaryClient mc = getMaryClient(); + BufferedReader inputReader = null; + // read requested input/output type from properties: + String inputType = System.getProperty("input.type", "TEXT"); + String outputType = System.getProperty("output.type", "AUDIO"); + String locale = System.getProperty("locale", "en_US"); + String audioType = System.getProperty("audio.type", "WAVE"); + if (!(audioType.equals("AIFC") + || audioType.equals("AIFF") + || audioType.equals("AU") + || audioType.equals("SND") + || audioType.equals("WAVE") + || audioType.equals("MP3") + || audioType.equals("Vorbis"))) { + System.err.println("Invalid value '" + audioType + "' for property 'audio.type'"); + System.err.println(); + usage(); + System.exit(1); + } + String defaultVoiceName = System.getProperty("voice.default"); + String defaultStyle = ""; + String defaultEffects = null; + String outputTypeParams = System.getProperty("output.type.params"); // null if not present + + if (args.length > 0) { + File file = new File(args[0]); + inputReader = new BufferedReader(new FileReader(file)); + } else { // no Filename, read from stdin: + inputReader = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); + } + + // Read input into a string: + StringBuilder sb = new StringBuilder(1024); + char[] buf = new char[1024]; + int nr; + while ((nr = inputReader.read(buf)) != -1) { + sb.append(buf, 0, nr); + } + + try { + mc.process(sb.toString(), inputType, outputType, locale, audioType, defaultVoiceName, defaultStyle, defaultEffects, outputTypeParams, System.out); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } + + +} + diff --git a/marytts-client/src/main/java/marytts/client/MaryFormData.java b/marytts-client/src/main/java/marytts/client/MaryFormData.java index 328aee8f..c3854c75 100644 --- a/marytts-client/src/main/java/marytts/client/MaryFormData.java +++ b/marytts-client/src/main/java/marytts/client/MaryFormData.java @@ -1,639 +1,639 @@ -/** - * Copyright 2007 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. - * - * This file is part of MARY TTS. - * - * MARY TTS is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - */ -package marytts.client; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.Vector; - -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.AudioFileFormat.Type; - -import marytts.util.MaryUtils; -import marytts.util.data.audio.MaryAudioUtils; -import marytts.util.http.Address; -import marytts.util.math.MathUtils; -import marytts.util.string.StringUtils; - -/** - * - * This class nests all the information and functions that a Mary client needs - * to receive/send data from/to server. - * To be able to use the functionality provided by this class, all Mary clients should either: - * (i) extend this class (Example: MaryHttpClient, MaryWebHttpClient) - * (ii) use an object of type MaryHttpForm or of a derived class (Example: MaryGUIClient) - * - * @author Oytun Türk - */ -public class MaryFormData -{ - // Default values which can be overridden from the command line. - private final String DEFAULT_HOST = "localhost"; - private final int DEFAULT_PORT = 59125; - - public Address hostAddress = null; - public String serverVersionInfo = null; - public String serverVersionNo = "unknown"; - public boolean serverCanStream = false; - - public Vector allVoices; - public Map> voicesByLocaleMap; - public Map> limitedDomainVoices; - public Set locales; - public Vector allDataTypes; - public Vector inputDataTypes; - public Vector outputDataTypes; - public Map serverExampleTexts; - public String currentExampleText; - public Map> voiceExampleTextsLimitedDomain; - public Map voiceExampleTextsGeneralDomain; - public Map audioEffectHelpTextsMap; - public Vector audioFileFormatTypes; - public Vector audioOutTypes; - public String inputText; - public String outputText; - public String errorMessage; - public boolean isOutputText; - public int voiceSelected; - public int inputTypeSelected; - public int outputTypeSelected; - public int audioFormatSelected; - public int audioOutSelected; - public int limitedDomainExampleTextSelected; - public String audioEffects; - public String audioEffectsHelpTextLineBreak; - public AudioEffectsBoxData effectsBoxData; - public Vector limitedDomainExampleTexts; - - public Map keyValuePairs; //Key-Value pairs for communication with server - - public String outputAudioResponseID; //output audio file for web browser client - public String mimeType; //MIME type for output audio (web browser clients) - - public MaryFormData() - { - String serverHost = System.getProperty("server.host", DEFAULT_HOST); - int serverPort = 0; - String helperString = System.getProperty("server.port"); - if (helperString != null) - serverPort = Integer.decode(helperString).intValue(); - else - serverPort = DEFAULT_PORT; - - Address serverAddress = new Address(serverHost, serverPort); - init(serverAddress, null, null, null, null, null, null, null, null); - } - - public MaryFormData(Address serverAddress) - { - init(serverAddress, null, null, null, null, null, null, null, null); - } - - public MaryFormData(Address serverAddress, - String versionIn, - String voicesIn, - String dataTypesIn, - String audioFileFormatTypesIn, - String audioEffectHelpTextLineBreakIn, - String defaultAudioEffects, - Vector defaultVoiceExampleTexts) - { - this(serverAddress, null, versionIn, voicesIn, dataTypesIn, audioFileFormatTypesIn, audioEffectHelpTextLineBreakIn, defaultAudioEffects, defaultVoiceExampleTexts); - } - - public MaryFormData(Address serverAddress, - Map keyValuePairsIn, - String versionIn, - String voicesIn, - String dataTypesIn, - String audioFileFormatTypesIn, - String audioEffectHelpTextLineBreakIn, - String defaultAudioEffects, - Vector defaultVoiceExampleTexts) - { - init(serverAddress, - keyValuePairsIn, - versionIn, - voicesIn, - dataTypesIn, - audioFileFormatTypesIn, - audioEffectHelpTextLineBreakIn, - defaultAudioEffects, - defaultVoiceExampleTexts); - } - - public void init(Address serverAddress, - Map keyValuePairsIn, - String versionIn, - String voicesIn, - String dataTypesIn, - String audioFileFormatTypesIn, - String audioEffectHelpTextLineBreakIn, - String defaultAudioEffects, - Vector defaultVoiceExampleTexts) - { - outputAudioResponseID = ""; - mimeType = ""; - hostAddress = null; - serverVersionInfo = null; - serverVersionNo = "unknown"; - serverCanStream = false; - - allVoices = null; - voicesByLocaleMap = null; - limitedDomainVoices = new HashMap>(); - allDataTypes = null; - inputDataTypes = null; - outputDataTypes = null; - serverExampleTexts = new HashMap(); - currentExampleText = ""; - voiceExampleTextsLimitedDomain = new HashMap>(); - voiceExampleTextsGeneralDomain = new HashMap(); - audioEffectHelpTextsMap = new HashMap(); - audioFileFormatTypes = null; - audioOutTypes = null; - inputText = ""; - outputText = ""; - isOutputText = false; - voiceSelected = 0; - inputTypeSelected = 0; - outputTypeSelected = 0; - audioFormatSelected = 0; - audioOutSelected = 0; - limitedDomainExampleTextSelected = 0; - audioEffects = ""; - audioEffectsHelpTextLineBreak = ""; - effectsBoxData = null; - keyValuePairs = new HashMap(); - limitedDomainExampleTexts = null; - - hostAddress = serverAddress; - - toServerVersionInfo(versionIn); - toVoices(voicesIn); - toDataTypes(dataTypesIn); - toAudioFileFormatAndOutTypes(audioFileFormatTypesIn); - toAudioEffectsHelpTextLineBreak(audioEffectHelpTextLineBreakIn); - toAudioEffects(defaultAudioEffects); - if (keyValuePairsIn != null) { - toSelections(keyValuePairsIn, defaultVoiceExampleTexts); - } - } - - public void toServerVersionInfo(String info) - { - serverVersionInfo = info; - - serverVersionNo = "unknown"; - - if (serverVersionInfo!=null) - { - String[] parts = serverVersionInfo.split(" "); - if (parts[0].equals("Mary") - && parts[1].equals("TTS") - && parts[2].equals("server") - && parts.length >= 4) { - // then parts[3] is the version number - serverVersionNo = parts[3]; - } - } - - if (serverVersionNo.equals("unknown") - || serverVersionNo.compareTo("3.0.1") < 0) { - serverCanStream = false; - } else { - serverCanStream = true; - } - } - - public void toVoices(String info) - { - allVoices = null; - voicesByLocaleMap = null; - limitedDomainVoices = null; - - if (info!=null && info.length()>0) - { - allVoices = new Vector(); - voicesByLocaleMap = new HashMap>(); - limitedDomainVoices = new HashMap>(); - String[] voiceStrings = info.split("\n"); - - for (int i=0; i localeVoices = null; - if (voicesByLocaleMap.containsKey(locale)) { - localeVoices = voicesByLocaleMap.get(locale); - } else { - localeVoices = new Vector(); - voicesByLocaleMap.put(locale, localeVoices); - } - localeVoices.add(voice); - } - } - } - - public void toDataTypes(String info) - { - allDataTypes = null; - inputDataTypes = null; - outputDataTypes = null; - - if (info!=null && info.length()>0) - { - allDataTypes = new Vector(); - inputDataTypes = new Vector(); - outputDataTypes = new Vector(); - - String[] typeStrings = info.split("\n"); - - for (int i=0; i(); - for (String localeName : StringUtils.toStringArray(info)) { - locales.add(MaryUtils.string2locale(localeName)); - } - } - - - public void toAudioFileFormatAndOutTypes(String info) - { - // TODO: this method uses code which is meaningful only - // in the server (MaryAudioUtils.canCreateMP3() etc.). - // It should be moved into the server code. - audioFileFormatTypes = null; - audioOutTypes = null; - - String[] allTypes = null; - int spaceInd; - - if (info!=null && info.length()>0) - allTypes = StringUtils.toStringArray(info); - - if (allTypes!=null) - { - for (int i=0; i(); - - audioFileFormatTypes.add(allTypes[i]); - - if (audioOutTypes==null) - audioOutTypes=new Vector(); - - audioOutTypes.add(typeName + "_FILE"); - - if (typeName.compareTo("MP3")==0) - audioOutTypes.add(typeName + "_STREAM"); - } - } - } - } - - public void toAudioEffectsHelpTextLineBreak(String strLineBreak) - { - if (strLineBreak!=null && strLineBreak.length()>0) - audioEffectsHelpTextLineBreak = strLineBreak; - else - audioEffectsHelpTextLineBreak = null; - } - - public void toAudioEffects(String availableAudioEffects) - { - if (availableAudioEffects!=null && availableAudioEffects.length()>0) - audioEffects = availableAudioEffects; - else - audioEffects = null; - - if (audioEffects!=null && audioEffects.length()>0) - effectsBoxData = new AudioEffectsBoxData(audioEffects); - else - effectsBoxData = null; - } - - - //Parse fullParamaters which is of the form key1=value1&key2=value2... - private void toSelections(Map keyValuePairsIn, Vector defaultVoiceExampleTexts) - { - assert keyValuePairsIn != null; - keyValuePairs = keyValuePairsIn; - - inputTypeSelected = 0; - inputText = ""; - if (outputDataTypes!=null && outputDataTypes.size()>0) - outputTypeSelected = outputDataTypes.size()-1; - else - outputTypeSelected = 0; - - isOutputText = false; - outputText = ""; - audioFormatSelected = 0; - voiceSelected = 0; - limitedDomainExampleTextSelected = 0; - - if (effectsBoxData==null) { - /*if (audioEffectsHelpTextLineBreak==null) - getAudioEffectHelpTextLineBreak(); - if (audioEffects==null) - getAudioEffects(); - */ - effectsBoxData = new AudioEffectsBoxData(audioEffects); - } - - int i; - String selected; - - //Input type selected - selected = keyValuePairs.get("INPUT_TYPE"); - if (selected!=null) { - for (i=0; i0) { - if (allVoices.elementAt(voiceSelected).isLimitedDomain()) { - limitedDomainExampleTexts = defaultVoiceExampleTexts; - - selected = keyValuePairs.get("exampletext"); - if (limitedDomainExampleTexts != null && selected!=null) { - for (i=0; i0 && inputDataTypes!=null && inputDataTypes.size()>0) - { - if (allVoices.elementAt(voiceSelected).isLimitedDomain() - && limitedDomainExampleTexts != null) - inputText = limitedDomainExampleTexts.get(limitedDomainExampleTextSelected); - else if (serverExampleTexts != null) - inputText = serverExampleTexts.get(inputDataTypes.get(inputTypeSelected).name()+" "+allVoices.elementAt(voiceSelected).getLocale().toString()); - } - } - // - - //Output text if non-audio output - if (isOutputText) - { - selected = keyValuePairs.get("OUTPUT_TEXT"); - if (selected!=null) - outputText = selected; - } - // - - //Audio out format selected: - //The clients can send audio format in two ways: - selected = keyValuePairs.get("AUDIO_OUT"); - - int spaceInd; - int scoreInd; - if (selected!=null) - { - scoreInd = selected.indexOf('_'); - String selectedTypeName = selected.substring(scoreInd+1); - for (i=0; i=0; - } - - - - //Check if all selections are appropriately made, i.e. no array bounds exceeded etc - public void checkAndCorrectSelections() - { - audioFormatSelected = MathUtils.CheckLimits(audioFormatSelected, 0, audioFileFormatTypes.size()-1); - audioOutSelected = MathUtils.CheckLimits(audioOutSelected, 0, audioOutTypes.size()-1); - inputTypeSelected = MathUtils.CheckLimits(inputTypeSelected, 0, inputDataTypes.size()-1); - outputTypeSelected = MathUtils.CheckLimits(outputTypeSelected, 0, outputDataTypes.size()-1); - voiceSelected = MathUtils.CheckLimits(voiceSelected, 0, allVoices.size()-1); - } - - /** - * This helper method converts a string (e.g., "en_US") into a - * proper Locale object. - * @param localeString a string representation of the locale - * @return a Locale object. - */ - public static Locale string2locale(String localeString) - { - Locale locale = null; - StringTokenizer localeST = new StringTokenizer(localeString, "_"); - String language = localeST.nextToken(); - String country = ""; - String variant = ""; - if (localeST.hasMoreTokens()) { - country = localeST.nextToken(); - if (localeST.hasMoreTokens()) { - variant = localeST.nextToken(); - } - } - locale = new Locale(language, country, variant); - return locale; - } -} - +/** + * Copyright 2007 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. + * + * This file is part of MARY TTS. + * + * MARY TTS is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + */ +package marytts.client; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFileFormat.Type; + +import marytts.util.MaryUtils; +import marytts.util.data.audio.MaryAudioUtils; +import marytts.util.http.Address; +import marytts.util.math.MathUtils; +import marytts.util.string.StringUtils; + +/** + * + * This class nests all the information and functions that a Mary client needs + * to receive/send data from/to server. + * To be able to use the functionality provided by this class, all Mary clients should either: + * (i) extend this class (Example: MaryHttpClient, MaryWebHttpClient) + * (ii) use an object of type MaryHttpForm or of a derived class (Example: MaryGUIClient) + * + * @author Oytun Türk + */ +public class MaryFormData +{ + // Default values which can be overridden from the command line. + private final String DEFAULT_HOST = "localhost"; + private final int DEFAULT_PORT = 59125; + + public Address hostAddress = null; + public String serverVersionInfo = null; + public String serverVersionNo = "unknown"; + public boolean serverCanStream = false; + + public Vector allVoices; + public Map> voicesByLocaleMap; + public Map> limitedDomainVoices; + public Set locales; + public Vector allDataTypes; + public Vector inputDataTypes; + public Vector outputDataTypes; + public Map serverExampleTexts; + public String currentExampleText; + public Map> voiceExampleTextsLimitedDomain; + public Map voiceExampleTextsGeneralDomain; + public Map audioEffectHelpTextsMap; + public Vector audioFileFormatTypes; + public Vector audioOutTypes; + public String inputText; + public String outputText; + public String errorMessage; + public boolean isOutputText; + public int voiceSelected; + public int inputTypeSelected; + public int outputTypeSelected; + public int audioFormatSelected; + public int audioOutSelected; + public int limitedDomainExampleTextSelected; + public String audioEffects; + public String audioEffectsHelpTextLineBreak; + public AudioEffectsBoxData effectsBoxData; + public Vector limitedDomainExampleTexts; + + public Map keyValuePairs; //Key-Value pairs for communication with server + + public String outputAudioResponseID; //output audio file for web browser client + public String mimeType; //MIME type for output audio (web browser clients) + + public MaryFormData() + { + String serverHost = System.getProperty("server.host", DEFAULT_HOST); + int serverPort = 0; + String helperString = System.getProperty("server.port"); + if (helperString != null) + serverPort = Integer.decode(helperString).intValue(); + else + serverPort = DEFAULT_PORT; + + Address serverAddress = new Address(serverHost, serverPort); + init(serverAddress, null, null, null, null, null, null, null, null); + } + + public MaryFormData(Address serverAddress) + { + init(serverAddress, null, null, null, null, null, null, null, null); + } + + public MaryFormData(Address serverAddress, + String versionIn, + String voicesIn, + String dataTypesIn, + String audioFileFormatTypesIn, + String audioEffectHelpTextLineBreakIn, + String defaultAudioEffects, + Vector defaultVoiceExampleTexts) + { + this(serverAddress, null, versionIn, voicesIn, dataTypesIn, audioFileFormatTypesIn, audioEffectHelpTextLineBreakIn, defaultAudioEffects, defaultVoiceExampleTexts); + } + + public MaryFormData(Address serverAddress, + Map keyValuePairsIn, + String versionIn, + String voicesIn, + String dataTypesIn, + String audioFileFormatTypesIn, + String audioEffectHelpTextLineBreakIn, + String defaultAudioEffects, + Vector defaultVoiceExampleTexts) + { + init(serverAddress, + keyValuePairsIn, + versionIn, + voicesIn, + dataTypesIn, + audioFileFormatTypesIn, + audioEffectHelpTextLineBreakIn, + defaultAudioEffects, + defaultVoiceExampleTexts); + } + + public void init(Address serverAddress, + Map keyValuePairsIn, + String versionIn, + String voicesIn, + String dataTypesIn, + String audioFileFormatTypesIn, + String audioEffectHelpTextLineBreakIn, + String defaultAudioEffects, + Vector defaultVoiceExampleTexts) + { + outputAudioResponseID = ""; + mimeType = ""; + hostAddress = null; + serverVersionInfo = null; + serverVersionNo = "unknown"; + serverCanStream = false; + + allVoices = null; + voicesByLocaleMap = null; + limitedDomainVoices = new HashMap>(); + allDataTypes = null; + inputDataTypes = null; + outputDataTypes = null; + serverExampleTexts = new HashMap(); + currentExampleText = ""; + voiceExampleTextsLimitedDomain = new HashMap>(); + voiceExampleTextsGeneralDomain = new HashMap(); + audioEffectHelpTextsMap = new HashMap(); + audioFileFormatTypes = null; + audioOutTypes = null; + inputText = ""; + outputText = ""; + isOutputText = false; + voiceSelected = 0; + inputTypeSelected = 0; + outputTypeSelected = 0; + audioFormatSelected = 0; + audioOutSelected = 0; + limitedDomainExampleTextSelected = 0; + audioEffects = ""; + audioEffectsHelpTextLineBreak = ""; + effectsBoxData = null; + keyValuePairs = new HashMap(); + limitedDomainExampleTexts = null; + + hostAddress = serverAddress; + + toServerVersionInfo(versionIn); + toVoices(voicesIn); + toDataTypes(dataTypesIn); + toAudioFileFormatAndOutTypes(audioFileFormatTypesIn); + toAudioEffectsHelpTextLineBreak(audioEffectHelpTextLineBreakIn); + toAudioEffects(defaultAudioEffects); + if (keyValuePairsIn != null) { + toSelections(keyValuePairsIn, defaultVoiceExampleTexts); + } + } + + public void toServerVersionInfo(String info) + { + serverVersionInfo = info; + + serverVersionNo = "unknown"; + + if (serverVersionInfo!=null) + { + String[] parts = serverVersionInfo.split(" "); + if (parts[0].equals("Mary") + && parts[1].equals("TTS") + && parts[2].equals("server") + && parts.length >= 4) { + // then parts[3] is the version number + serverVersionNo = parts[3]; + } + } + + if (serverVersionNo.equals("unknown") + || serverVersionNo.compareTo("3.0.1") < 0) { + serverCanStream = false; + } else { + serverCanStream = true; + } + } + + public void toVoices(String info) + { + allVoices = null; + voicesByLocaleMap = null; + limitedDomainVoices = null; + + if (info!=null && info.length()>0) + { + allVoices = new Vector(); + voicesByLocaleMap = new HashMap>(); + limitedDomainVoices = new HashMap>(); + String[] voiceStrings = info.split("\n"); + + for (int i=0; i localeVoices = null; + if (voicesByLocaleMap.containsKey(locale)) { + localeVoices = voicesByLocaleMap.get(locale); + } else { + localeVoices = new Vector(); + voicesByLocaleMap.put(locale, localeVoices); + } + localeVoices.add(voice); + } + } + } + + public void toDataTypes(String info) + { + allDataTypes = null; + inputDataTypes = null; + outputDataTypes = null; + + if (info!=null && info.length()>0) + { + allDataTypes = new Vector(); + inputDataTypes = new Vector(); + outputDataTypes = new Vector(); + + String[] typeStrings = info.split("\n"); + + for (int i=0; i(); + for (String localeName : StringUtils.toStringArray(info)) { + locales.add(MaryUtils.string2locale(localeName)); + } + } + + + public void toAudioFileFormatAndOutTypes(String info) + { + // TODO: this method uses code which is meaningful only + // in the server (MaryAudioUtils.canCreateMP3() etc.). + // It should be moved into the server code. + audioFileFormatTypes = null; + audioOutTypes = null; + + String[] allTypes = null; + int spaceInd; + + if (info!=null && info.length()>0) + allTypes = StringUtils.toStringArray(info); + + if (allTypes!=null) + { + for (int i=0; i(); + + audioFileFormatTypes.add(allTypes[i]); + + if (audioOutTypes==null) + audioOutTypes=new Vector(); + + audioOutTypes.add(typeName + "_FILE"); + + if (typeName.compareTo("MP3")==0) + audioOutTypes.add(typeName + "_STREAM"); + } + } + } + } + + public void toAudioEffectsHelpTextLineBreak(String strLineBreak) + { + if (strLineBreak!=null && strLineBreak.length()>0) + audioEffectsHelpTextLineBreak = strLineBreak; + else + audioEffectsHelpTextLineBreak = null; + } + + public void toAudioEffects(String availableAudioEffects) + { + if (availableAudioEffects!=null && availableAudioEffects.length()>0) + audioEffects = availableAudioEffects; + else + audioEffects = null; + + if (audioEffects!=null && audioEffects.length()>0) + effectsBoxData = new AudioEffectsBoxData(audioEffects); + else + effectsBoxData = null; + } + + + //Parse fullParamaters which is of the form key1=value1&key2=value2... + private void toSelections(Map keyValuePairsIn, Vector defaultVoiceExampleTexts) + { + assert keyValuePairsIn != null; + keyValuePairs = keyValuePairsIn; + + inputTypeSelected = 0; + inputText = ""; + if (outputDataTypes!=null && outputDataTypes.size()>0) + outputTypeSelected = outputDataTypes.size()-1; + else + outputTypeSelected = 0; + + isOutputText = false; + outputText = ""; + audioFormatSelected = 0; + voiceSelected = 0; + limitedDomainExampleTextSelected = 0; + + if (effectsBoxData==null) { + /*if (audioEffectsHelpTextLineBreak==null) + getAudioEffectHelpTextLineBreak(); + if (audioEffects==null) + getAudioEffects(); + */ + effectsBoxData = new AudioEffectsBoxData(audioEffects); + } + + int i; + String selected; + + //Input type selected + selected = keyValuePairs.get("INPUT_TYPE"); + if (selected!=null) { + for (i=0; i0) { + if (allVoices.elementAt(voiceSelected).isLimitedDomain()) { + limitedDomainExampleTexts = defaultVoiceExampleTexts; + + selected = keyValuePairs.get("exampletext"); + if (limitedDomainExampleTexts != null && selected!=null) { + for (i=0; i0 && inputDataTypes!=null && inputDataTypes.size()>0) + { + if (allVoices.elementAt(voiceSelected).isLimitedDomain() + && limitedDomainExampleTexts != null) + inputText = limitedDomainExampleTexts.get(limitedDomainExampleTextSelected); + else if (serverExampleTexts != null) + inputText = serverExampleTexts.get(inputDataTypes.get(inputTypeSelected).name()+" "+allVoices.elementAt(voiceSelected).getLocale().toString()); + } + } + // + + //Output text if non-audio output + if (isOutputText) + { + selected = keyValuePairs.get("OUTPUT_TEXT"); + if (selected!=null) + outputText = selected; + } + // + + //Audio out format selected: + //The clients can send audio format in two ways: + selected = keyValuePairs.get("AUDIO_OUT"); + + int spaceInd; + int scoreInd; + if (selected!=null) + { + scoreInd = selected.indexOf('_'); + String selectedTypeName = selected.substring(scoreInd+1); + for (i=0; i=0; + } + + + + //Check if all selections are appropriately made, i.e. no array bounds exceeded etc + public void checkAndCorrectSelections() + { + audioFormatSelected = MathUtils.CheckLimits(audioFormatSelected, 0, audioFileFormatTypes.size()-1); + audioOutSelected = MathUtils.CheckLimits(audioOutSelected, 0, audioOutTypes.size()-1); + inputTypeSelected = MathUtils.CheckLimits(inputTypeSelected, 0, inputDataTypes.size()-1); + outputTypeSelected = MathUtils.CheckLimits(outputTypeSelected, 0, outputDataTypes.size()-1); + voiceSelected = MathUtils.CheckLimits(voiceSelected, 0, allVoices.size()-1); + } + + /** + * This helper method converts a string (e.g., "en_US") into a + * proper Locale object. + * @param localeString a string representation of the locale + * @return a Locale object. + */ + public static Locale string2locale(String localeString) + { + Locale locale = null; + StringTokenizer localeST = new StringTokenizer(localeString, "_"); + String language = localeST.nextToken(); + String country = ""; + String variant = ""; + if (localeST.hasMoreTokens()) { + country = localeST.nextToken(); + if (localeST.hasMoreTokens()) { + variant = localeST.nextToken(); + } + } + locale = new Locale(language, country, variant); + return locale; + } +} + diff --git a/marytts-client/src/main/java/marytts/client/MaryGUIClient.java b/marytts-client/src/main/java/marytts/client/MaryGUIClient.java index 57a3c41a..8d9ef66f 100644 --- a/marytts-client/src/main/java/marytts/client/MaryGUIClient.java +++ b/marytts-client/src/main/java/marytts/client/MaryGUIClient.java @@ -1,6 +1,6 @@ -/** - * Copyright 2000-2009 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. +/** + * Copyright 2000-2009 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * @@ -17,1422 +17,1422 @@ * along with this program. If not, see . * */ -package marytts.client; - -//General Java Classes -import java.awt.Color; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.FocusTraversalPolicy; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.KeyboardFocusManager; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; -import java.net.UnknownHostException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.ImageIcon; -import javax.swing.JApplet; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextPane; -import javax.swing.KeyStroke; -import javax.swing.filechooser.FileFilter; -import javax.swing.text.BadLocationException; -import javax.swing.text.SimpleAttributeSet; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; - -import marytts.client.http.MaryHttpClient; -import marytts.util.MaryUtils; -import marytts.util.http.Address; -import marytts.util.io.SimpleFileFilter; - -import org.incava.util.diff.Diff; -import org.incava.util.diff.Difference; - - - - -/** - * A GUI Interface to the Mary Client, allowing to access and modify - * intermediate processing results. - * @author Marc.Schroeder, oytun.turk - * @see MaryHttpClient The client implementation - */ - -public class MaryGUIClient extends JPanel -{ - - /* -------------------- GUI stuff -------------------- */ - - private Dimension paneDimension; - // Input - private JPanel inputTypePanel; - private JComboBox cbInputType; - private JPanel inputPanel; - private JScrollPane inputScrollPane; - private JTextPane inputText; - private JPanel voicePanel; - private JComboBox cbDefaultVoice; - private JComboBox cbVoiceExampleText; - private boolean doReplaceInput = true; - // When the user changes input type, he is offered an example text for - // the new input type. In order to prevent this when setting a new input - // type from within the program, doReplaceInput must be set to false - // before triggering the selection changed event. - - // Output - private boolean showingTextOutput = true; - private JPanel outputTypePanel; - private JComboBox cbOutputType; - private JButton bSaveOutput; - private JTextPane outputText; - private JScrollPane outputScrollPane; - private JPanel audioPanel; - private JButton bPlay; - private JPanel savePanel; - - //Audio effects - private boolean isButtonHide = true; - private boolean showingAudioEffects = false; - private JPanel showHidePanel; - private JButton showHideEffects; - private JList effectsList; - private AudioEffectsBoxGUI effectsBox; - private String [] effectNames; - private String [] exampleParams; - private String [] helpTexts; - // - - // Processing Buttons - private JPanel buttonPanel; - private JButton bProcess; - private JButton bEdit; - private JButton bCompare; - - static JFrame mainFrame; - static JApplet mainApplet; - - /* -------------------- Data and Processing stuff -------------------- */ - private MaryClient processor; - - private marytts.util.data.audio.AudioPlayer audioPlayer = null; - private boolean allowSave; - private boolean streamMp3 = false; - private MaryClient.Voice prevVoice = null; - - //Map of limited Domain Voices and their example Texts - private Map> limDomVoices = new HashMap>(); - - private GridBagLayout gridBagLayout; - private GridBagConstraints gridC; - - static FocusTraversalPolicy maryGUITraversal; - - /** - * Create a MaryGUIClient instance that connects to the server host - * and port as specified in the system properties "server.host" and "server.port", - * which default to "cling.dfki.uni-sb.de" and 59125, respectively. - * @throws IOException - * @throws UnknownHostException - */ - public MaryGUIClient() throws Exception - { - super(); - // First the MaryHttpClient processor class, because it may provide - // information needed in the GUI creation. - try { - processor = MaryClient.getMaryClient(); - streamMp3 = Boolean.getBoolean("stream.mp3"); - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(null, - e.getMessage(), - "Cannot connect to server", - JOptionPane.ERROR_MESSAGE); - System.exit(1); - } - allowSave = true; - init(); - } - - /** - * Create a MaryGUIClient instance that connects to the given server host - * and port. This is meant to be used from Applets. - * @param host - * @param port - * @throws IOException - * @throws UnknownHostException - */ - public MaryGUIClient(Address hostAddress, JApplet applet) throws IOException - { - super(); - // First the MaryHttpClient processor class, because it may provide - // information needed in the GUI creation. - try { - processor = new MaryHttpClient(hostAddress, false, false); - } catch (Exception e) { - System.out.println("Problem creating mary client"); - e.printStackTrace(); - JOptionPane.showMessageDialog(null, - e.getMessage(), - "Cannot connect to server", - JOptionPane.ERROR_MESSAGE); - System.exit(1); - } - mainApplet = applet; - allowSave = false; - init(); - } - - /** - * Create an instance of the MaryHttpClient class which does the processing, - * and initialise the GUI. - * @throws InterruptedException - * @throws IOException - * @throws Exception - */ - public void init() throws IOException - { - maryGUITraversal = new MaryGUIFocusTraversalPolicy(); - //if this is a normal gui - if (mainFrame != null){ - mainFrame.setFocusTraversalPolicy(maryGUITraversal); - } else { //this is an applet - mainApplet.setFocusTraversalPolicy(maryGUITraversal); - } - - paneDimension = new Dimension(250,400); - // Layout - gridBagLayout = new GridBagLayout(); - gridC = new GridBagConstraints(); - - gridC.insets = new Insets( 2,2,2,2 ); - gridC.weightx = 0.1; - gridC.weighty = 0.1; - setLayout(gridBagLayout); - - //////////////// Left Column: Input ///////////////////// - // Input type - inputTypePanel = new JPanel(); - inputTypePanel.setLayout(new FlowLayout(FlowLayout.LEADING)); - gridC.gridx = 0; - gridC.gridy = 0; - gridC.gridwidth = 3; - gridC.fill = GridBagConstraints.HORIZONTAL; - gridBagLayout.setConstraints( inputTypePanel, gridC ); - add( inputTypePanel ); - gridC.gridwidth = 1; - JLabel inputTypeLabel = new JLabel( "Input Type: " ); - inputTypePanel.add(inputTypeLabel); - assert processor.getInputDataTypes().size() > 0; - assert processor.getOutputDataTypes().size() > 0; - cbInputType = new JComboBox( processor.getInputDataTypes() ); - cbInputType.setName("Input Type"); - cbInputType.getAccessibleContext().setAccessibleName("Input Type selection"); - cbInputType.setToolTipText( "Specify the type of data contained " + - "in the input text area below." ); - cbInputType.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - verifyExamplesVisible(); - if (doReplaceInput) { - setExampleInputText(); - } else { - // input text was set by other code - doReplaceInput = true; - } - //setOutputTypeItems(); - } - } - }); - inputTypePanel.add( cbInputType ); - - //Input Text area - inputPanel = new JPanel(); - inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS)); - inputPanel.setMinimumSize(paneDimension); - inputPanel.setPreferredSize(paneDimension); - gridC.gridx = 0; - gridC.gridy = 1; - gridC.gridwidth = 3; - gridC.gridheight = 3; - gridC.weightx = 0.4; - gridC.weighty = 0.8; - //gridC.ipadx = 270; - //gridC.ipady = 200; - gridC.fill = GridBagConstraints.BOTH; - gridBagLayout.setConstraints( inputPanel, gridC ); - add( inputPanel ); - gridC.gridwidth = 1; - gridC.gridheight = 1; - gridC.weightx = 0.1; - gridC.weighty = 0.1; - gridC.ipadx = 0; - gridC.ipady = 0; - gridC.fill = GridBagConstraints.NONE; - inputText = new JTextPane(); - - inputText.getAccessibleContext().setAccessibleName("Input Text Area"); - - //Set Tab and Shift-Tab for Keyboard movement - Set forwardKeys = new HashSet(); - forwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0, false)); - inputText.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,forwardKeys); - Set backwardKeys = new HashSet(); - backwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,KeyEvent.SHIFT_MASK+KeyEvent.SHIFT_DOWN_MASK, false)); - inputText.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,backwardKeys); - - inputScrollPane = new JScrollPane(inputText); - inputPanel.add(inputScrollPane); - inputScrollPane.setPreferredSize(new Dimension(inputPanel.getPreferredSize().width, 1000)); - //example text for limDom voices - cbVoiceExampleText = new JComboBox(); - cbVoiceExampleText.setName("Example Text"); - cbVoiceExampleText.getAccessibleContext().setAccessibleName("Example text selection"); - cbVoiceExampleText.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - if (doReplaceInput - && ((MaryClient.DataType)cbInputType.getSelectedItem()).name().startsWith("TEXT")) - setInputText((String)cbVoiceExampleText.getSelectedItem()); - } - } - }); - cbVoiceExampleText.setPreferredSize(new Dimension(inputPanel.getPreferredSize().width, 25)); - inputPanel.add(cbVoiceExampleText); - - // Select voice - voicePanel = new JPanel(); - voicePanel.setLayout(new FlowLayout(FlowLayout.LEADING)); - gridC.gridx = 0; - gridC.gridy = 4; - gridC.gridwidth = 4; - gridC.gridheight = 2; - gridC.fill = GridBagConstraints.HORIZONTAL; - gridBagLayout.setConstraints( voicePanel, gridC ); - add( voicePanel ); - gridC.gridwidth = 1; - gridC.gridheight = 1; - JLabel voiceLabel = new JLabel("Voice:"); - voicePanel.add( voiceLabel ); - cbDefaultVoice = new JComboBox(); - cbDefaultVoice.setName("Voice selection"); - cbDefaultVoice.getAccessibleContext().setAccessibleName("Voice selection"); - voicePanel.add( cbDefaultVoice ); - cbDefaultVoice.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - fillExampleTexts(); - verifyExamplesVisible(); - MaryClient.Voice voice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); - MaryClient.DataType dataType = (MaryClient.DataType)cbInputType.getSelectedItem(); - if (doReplaceInput - && (voice.isLimitedDomain() && dataType.name().startsWith("TEXT") - || getPrevVoice() == null - || !getPrevVoice().getLocale().equals(voice.getLocale()))) - setExampleInputText(); - setPrevVoice(voice); - - updateAudioEffects(); - } - } - }); - - // For the limited domain voices, get example texts: - Vector voices = processor.getVoices(); - if (voices != null) { - for (MaryClient.Voice v : voices) { - if (v.isLimitedDomain()){ - limDomVoices.put(v.name(), processor.getVoiceExampleTextsLimitedDomain(v.name())); - } - } - } - - verifyDefaultVoices(); - fillExampleTexts(); - verifyExamplesVisible(); - setExampleInputText(); - - //////////////// Centre Column: Buttons ///////////////////// - // Action buttons in centre - buttonPanel = new JPanel(); - buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); - gridC.gridx = 3; - gridC.gridy = 1; - gridC.gridheight = 3; - gridC.fill = GridBagConstraints.BOTH; - gridBagLayout.setConstraints( buttonPanel, gridC ); - add( buttonPanel ); - bProcess = new JButton( "Process ->" ); - bProcess.setToolTipText( "Call the Mary Server." + - "The input will be transformed into the specified output type." ); - bProcess.getAccessibleContext().setAccessibleName("Process button"); - bProcess.setActionCommand( "process" ); - bProcess.setMnemonic('P'); - bProcess.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - processInput(); - verifyEnableButtons(); - } - }); - buttonPanel.add(Box.createVerticalGlue()); - buttonPanel.add( bProcess ); - bProcess.setAlignmentX(Component.CENTER_ALIGNMENT); - buttonPanel.add(Box.createVerticalGlue()); - - bEdit = new JButton( "<- Edit" ); - bEdit.setToolTipText( "Edit the content of the output text area as the new input." + - " The current content of the input text area will be discarded." ); - bEdit.getAccessibleContext().setAccessibleName("Edit button"); - bEdit.setActionCommand( "edit" ); - bEdit.setMnemonic('E'); - bEdit.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editOutput(); - verifyEnableButtons(); - } - }); - buttonPanel.add( bEdit ); - bEdit.setAlignmentX(Component.CENTER_ALIGNMENT); - buttonPanel.add(Box.createVerticalGlue()); - - bCompare = new JButton( "<- Compare ->" ); - bCompare.setToolTipText( "Compare input and output" + - "(available only if both are MaryXML types)." ); - bCompare.getAccessibleContext().setAccessibleName("Compare button"); - bCompare.setActionCommand( "compare" ); - bCompare.setMnemonic('C'); - bCompare.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - compareTexts(); - verifyEnableButtons(); - } - }); - buttonPanel.add( bCompare ); - bCompare.setAlignmentX(Component.CENTER_ALIGNMENT); - buttonPanel.add(Box.createVerticalGlue()); - buttonPanel.setPreferredSize(new Dimension(buttonPanel.getPreferredSize().width, paneDimension.height)); - - //////////////// Right Column: Output ///////////////////// - // Output type - outputTypePanel = new JPanel(); - outputTypePanel.setLayout(new FlowLayout(FlowLayout.TRAILING)); - gridC.gridx = 4; - gridC.gridy = 0; - gridC.gridwidth = 3; - gridC.gridheight = 1; - gridC.ipady = 10; - gridC.fill = GridBagConstraints.HORIZONTAL; - gridBagLayout.setConstraints( outputTypePanel, gridC ); - add( outputTypePanel ); - gridC.ipady = 0; - gridC.gridwidth = 1; - JLabel outputTypeLabel = new JLabel( "Output Type: " ); - outputTypePanel.add( outputTypeLabel ); - cbOutputType = new JComboBox(); - cbOutputType.setName("Output type"); - cbOutputType.getAccessibleContext().setAccessibleName("Output type selection"); - setOutputTypeItems(); - // The last possible output type (= audio) is the default - // output type: - cbOutputType.setSelectedIndex(cbOutputType.getItemCount() - 1); - cbOutputType.setToolTipText( "Specify the output type for the next " + - "processing action (Process button)." ); - cbOutputType.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - verifyOutputDisplay(); - verifyEnableButtons(); - revalidate(); - } - } - }); - outputTypePanel.add( cbOutputType ); - - // Output Text area - if (((MaryClient.DataType)cbOutputType.getSelectedItem()).isTextType()) - showingTextOutput = true; - else - showingTextOutput = false; - outputText = new JTextPane(); - outputText.getAccessibleContext().setAccessibleName("Output text"); - - //set tab and shift-tab for keyboard movement - outputText.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,forwardKeys); - outputText.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,backwardKeys); - - // outputText.setLineWrap(false); - outputText.setEditable(false); - outputScrollPane = new JScrollPane(outputText); - outputScrollPane.setMinimumSize(paneDimension); - outputScrollPane.setPreferredSize(paneDimension); - gridC.gridx = 4; - gridC.gridy = 1; - gridC.gridwidth = 3; - gridC.gridheight = 3; - gridC.weightx = 0.4; - gridC.weighty = 0.8; - gridC.fill = GridBagConstraints.BOTH; - gridBagLayout.setConstraints(outputScrollPane, gridC); - if (!showingTextOutput) - outputScrollPane.setVisible(false); - add( outputScrollPane ); - - //Audio effects - setAudioEffects(); - - isButtonHide = false; - if (effectsBox.hasEffects()) - { - gridC.gridx = 4; - gridC.gridy = 1; - gridC.gridwidth = 3; - gridC.gridheight = 3; - gridC.weightx = 0.1; - gridC.weighty = 0.1; - gridC.ipadx = 0; - gridC.ipady = 0; - gridC.fill = GridBagConstraints.BOTH; - gridBagLayout.setConstraints(effectsBox.mainPanel, gridC); - - add(effectsBox.mainPanel); - - updateAudioEffects(); - - if (effectsBox!=null && effectsBox.mainPanel!=null) - { - showHidePanel = new JPanel(); - showHidePanel.setPreferredSize(paneDimension); - showHidePanel.setLayout( new BoxLayout(showHidePanel, BoxLayout.Y_AXIS) ); - - if (!showingTextOutput) - { - showHideEffects = new JButton("Hide Effects"); - isButtonHide = true; - } - else - { - showHideEffects = new JButton("Show Effects"); - isButtonHide = false; - } - - showHideEffects.setToolTipText( "Hide or show available audio effects for post-processing the TTS output" ); - showHideEffects.getAccessibleContext().setAccessibleName("Hide/Show audio effects button"); - - showHideEffects.addActionListener( new ActionListener() { - public void actionPerformed(ActionEvent e) { - showHideEffectAction(); - } - }); - - showHidePanel.add(Box.createVerticalGlue()); - showHidePanel.add(showHideEffects); - showHidePanel.add(Box.createVerticalGlue()); - showHideEffects.setAlignmentX(Component.CENTER_ALIGNMENT); - - gridC.gridx = 4; - if (!showingTextOutput) - gridC.gridy = 4; - else - gridC.gridy = 3; - - gridC.gridwidth = 3; - gridC.gridheight = 1; - gridC.ipady = 10; - gridC.fill = GridBagConstraints.BOTH; - gridBagLayout.setConstraints(showHidePanel, gridC); - add(showHidePanel); - gridC.ipady = 0; - - if (effectsBox.mainPanel!=null) - { - if (!showingTextOutput && isButtonHide) - { - effectsBox.mainPanel.setVisible(true); - showingAudioEffects = true; - } - else - { - effectsBox.mainPanel.setVisible(false); - showingAudioEffects = false; - } - } - } - } - // - - gridC.gridwidth = 1; - gridC.gridheight = 1; - gridC.weightx = 0.1; - gridC.weighty = 0.1; - gridC.ipadx = 0; - gridC.ipady = 0; - gridC.fill = GridBagConstraints.NONE; - - // Overlapping location: Audio play button - audioPanel = new JPanel(); - audioPanel.setPreferredSize(paneDimension); - audioPanel.setLayout( new BoxLayout(audioPanel, BoxLayout.Y_AXIS) ); - bPlay = new JButton( "Play" ); - bPlay.setToolTipText( "Synthesize and play the resulting audio stream." ); - bPlay.getAccessibleContext().setAccessibleName("Play button"); - bPlay.setActionCommand( "play" ); - bPlay.setMnemonic('P'); - bPlay.addActionListener( new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (audioPlayer != null) { // an audioPlayer is currently playing - audioPlayer.cancel(); - audioPlayer = null; - bPlay.setText("Play"); - } else { - processInput(); - } - } - }); - audioPanel.add(Box.createVerticalGlue()); - audioPanel.add(bPlay); - audioPanel.add(Box.createVerticalGlue()); - bPlay.setAlignmentX(Component.CENTER_ALIGNMENT); - //bPlay.setMaximumSize(bPlay.getPreferredSize()); - - if (showingTextOutput) - audioPanel.setVisible(false); - gridC.gridx = 4; - if (showingAudioEffects) - gridC.gridy = 5; - else - gridC.gridy = 4; - gridC.gridwidth = 3; - gridC.gridheight = 1; - gridC.ipady = 10; - gridC.fill = GridBagConstraints.BOTH; - gridBagLayout.setConstraints(audioPanel, gridC); - add( audioPanel ); - gridC.gridwidth = 1; - gridC.ipady = 0; - - // Output Save button - if (allowSave) { - savePanel = new JPanel(); - savePanel.setLayout(new FlowLayout(FlowLayout.TRAILING)); - gridC.gridx = 4; - gridC.ipady = 10; - if (showingAudioEffects) - gridC.gridy = 6; - else - gridC.gridy = 5; - - gridC.fill = GridBagConstraints.HORIZONTAL; - gridBagLayout.setConstraints( savePanel, gridC ); - add(savePanel); - ImageIcon saveIcon = new ImageIcon("save.gif"); - bSaveOutput = new JButton( "Save...", saveIcon ); - bSaveOutput.setToolTipText( "Save the output as a file." ); - bSaveOutput.getAccessibleContext().setAccessibleName("Save Output button"); - bSaveOutput.setActionCommand( "saveOutput" ); - bSaveOutput.setMnemonic('S'); - bSaveOutput.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - try { - saveOutput(); - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (InterruptedException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - } - }); - savePanel.add( bSaveOutput ); - gridC.ipady = 0; - } - setPreferredSize(new Dimension(720,480)); - - verifyEnableButtons(); - cbInputType.requestFocusInWindow(); - - showHideEffectAction(); - } - - private void setAudioEffects() - { - String availableAudioEffects = ""; - String strLineBreak = ""; - - try { - availableAudioEffects = processor.getAudioEffects(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - effectsBox = new AudioEffectsBoxGUI(availableAudioEffects); - // TODO: this is overkill, we could load a help text when the - // user presses a help button, but it would require re-engineering the code a bit. - // fill help through separate queries: - for (int i=0; i< effectsBox.getData().getTotalEffects(); i++) { - AudioEffectControlData eff = effectsBox.getData().getControlData(i); - try { - eff.setHelpText(processor.requestEffectHelpText(eff.getEffectName())); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - - private void showHideEffectAction() - { - if (isButtonHide) - { - if (effectsBox!=null && effectsBox.mainPanel!=null) - effectsBox.mainPanel.setVisible(false); - - if (showHideEffects!=null) - showHideEffects.setText("Show Effects"); - - isButtonHide = false; - showingAudioEffects = false; - } - else - { - if (effectsBox!=null && effectsBox.mainPanel!=null) - effectsBox.mainPanel.setVisible(true); - - if (showHideEffects!=null) - showHideEffects.setText("Hide Effects"); - - isButtonHide = true; - showingAudioEffects = true; - } - } - - //If there are any effects available for the selected voice - // update audio effects box accordingly - private void updateAudioEffects() - { - //Overlapping location: Audio effects box - //Initialize the effects here (normally using info from the server) - if (effectsBox != null) - { - if (effectsBox.hasEffects() && effectsBox.getData().getTotalEffects()>0) - { - MaryClient.Voice voice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); - if (voice == null) return; - - for (int i=0; i 0) effects.append("+"); - effects.append(name); - if (params != null && params.length()>0) { - effects.append("(").append(params).append(")"); - } - } - } - } - return effects.toString(); - } - - - - - private void setExampleInputText() - { - MaryClient.Voice defaultVoice = (MaryClient.Voice) cbDefaultVoice.getSelectedItem(); - if (defaultVoice == null) return; - MaryClient.DataType inputType = (MaryClient.DataType) cbInputType.getSelectedItem(); - if (defaultVoice.isLimitedDomain() && inputType.name().startsWith("TEXT")) { - setInputText((String) cbVoiceExampleText.getSelectedItem()); - } else { - try { - String exampleText = processor.getServerExampleText(inputType.name(), defaultVoice.getLocale().toString()); - setInputText(exampleText); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - private void fillExampleTexts() - { - MaryClient.Voice defaultVoice = (MaryClient.Voice) cbDefaultVoice.getSelectedItem(); - if (defaultVoice == null || !defaultVoice.isLimitedDomain()) return; - Vector sentences = (Vector)limDomVoices.get(defaultVoice.name()); - assert sentences != null; - cbVoiceExampleText.removeAllItems(); - for (int i = 0; i 0) { - bCompare.setEnabled(true); - } else { - bCompare.setEnabled(false); - } - } - - - /** - * Verify that the list of voices in cbDefaultVoices matches the language of the input format. - * @throws InterruptedException - * @throws IOException - */ - private void verifyDefaultVoices() throws IOException - { - MaryClient.DataType inputType = (MaryClient.DataType)cbInputType.getSelectedItem(); - // Is the default voice still suitable for the input locale? - MaryClient.Voice defaultVoice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); - // Reset the list, just in case - cbDefaultVoice.removeAllItems(); - Vector voices = processor.getVoices(); - if (voices != null) { - for (MaryClient.Voice v : processor.getVoices()) { - cbDefaultVoice.addItem(v); - } - if (defaultVoice != null) { - cbDefaultVoice.setSelectedItem(defaultVoice); - } else { // First in list is default voice: - cbDefaultVoice.setSelectedIndex(0); - } - } - } - - - - private void setOutputTypeItems() throws IOException - { - MaryClient.DataType inputType = (MaryClient.DataType) cbInputType.getSelectedItem(); - MaryClient.DataType selectedItem = (MaryClient.DataType) cbOutputType.getSelectedItem(); - cbOutputType.removeAllItems(); - for (MaryClient.DataType d : processor.getOutputDataTypes()) { - cbOutputType.addItem(d); - } - cbOutputType.setSelectedItem(selectedItem); - } - - private void verifyOutputDisplay() - { - if (((MaryClient.DataType)cbOutputType.getSelectedItem()).isTextType()) - { - setOutputText(""); // erase the output text - if (!showingTextOutput) - { - // showing Audio Output - // need to change output display - audioPanel.setVisible(false); - - if (effectsBox!=null) - { - if (effectsBox.mainPanel!=null) - effectsBox.mainPanel.setVisible(false); - - if (showHidePanel!=null) - showHidePanel.setVisible(false); - } - - outputScrollPane.setVisible(true); - showingTextOutput = true; - revalidate(); - } - } - else - { // Audio output - if (showingTextOutput) - { - // change output display - outputScrollPane.setVisible(false); - audioPanel.setVisible(true); - - if (effectsBox!=null && effectsBox.mainPanel!=null) - { - if (showHidePanel!=null) - showHidePanel.setVisible(true); - - if (effectsBox.mainPanel!=null && isButtonHide) - effectsBox.mainPanel.setVisible(true); - } - - showingTextOutput = false; - revalidate(); - } - } - } - - - /* -------------------- Processing callers -------------------- */ - private File lastDirectory = null; - private String lastExtension = null; - private void saveOutput() throws IOException, InterruptedException - { - if (!allowSave) return; - try { - if (showingTextOutput) { - JFileChooser fc = new JFileChooser(); - if (lastDirectory != null) { - fc.setCurrentDirectory(lastDirectory); - } - int returnVal = fc.showSaveDialog(this); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File saveFile = fc.getSelectedFile(); - lastDirectory = saveFile.getParentFile(); - PrintWriter w = new PrintWriter(new FileWriter(saveFile)); - w.print(outputText.getText()); - w.close(); - } - } else { // audio data - JFileChooser fc = new JFileChooser(); - if (lastDirectory != null) { - fc.setCurrentDirectory(lastDirectory); - } - Vector knownAudioTypes = processor.getAudioFileFormatTypes(); - String[] extensions = new String[knownAudioTypes.size()]; - String[] typeNames = new String[knownAudioTypes.size()]; - FileFilter defaultFilter = null; - for (int i=0; i to bold. - * This is "dumb", i.e. it will not try to analyse the contents of - * tags, and fail at situations like , where i would - * be printed in bold as well. - */ - private void highlightText(StyledDocument doc) { - SimpleAttributeSet highlighted = new SimpleAttributeSet(); - StyleConstants.setBold(highlighted, true); - boolean insideTag = false; - int beginText = -1; // will contain beginning of text to be highlighted - for (int i=0; i') - insideTag = false; - } else { // not inside a tag - if (c == '<') { - // Start of new tag - if (beginText != -1) { // anything to highlight? - // highlight it - doc.setCharacterAttributes(beginText, i-beginText, - highlighted, false); - beginText = -1; - } - insideTag = true; - } else { // normal text character - if (beginText == -1) { - // This is the first text character - beginText = i; - } - } - } - } // for all characters in document - // Any text at the very end of the document? - if (beginText != -1) { - doc.setCharacterAttributes(beginText, doc.getLength()-beginText, - highlighted, false); - } - } - - // Call the mary client - private void processInput() - { - OutputStream os; - MaryClient.DataType outputType = (MaryClient.DataType)cbOutputType.getSelectedItem(); - if (outputType.name().equals("AUDIO")) { - try { - audioPlayer = new marytts.util.data.audio.AudioPlayer(); - processor.streamAudio(inputText.getText(), - ((MaryClient.DataType)cbInputType.getSelectedItem()).name(), - ((MaryClient.Voice)cbDefaultVoice.getSelectedItem()).getLocale().toString(), - streamMp3 ? "MP3":"AU", - ((MaryClient.Voice)cbDefaultVoice.getSelectedItem()).name(), - "", - getAudioEffectsString(), - audioPlayer, - new MaryHttpClient.AudioPlayerListener() { - public void playerFinished() - { - resetPlayButton(); - } - public void playerException(Exception e) - { - showErrorMessage(e.getClass().getName(), e.getMessage()); - resetPlayButton(); - } - }); - bPlay.setText("Stop"); - } catch (Exception e) { - e.printStackTrace(); - showErrorMessage(e.getClass().getName(), e.getMessage()); - resetPlayButton(); - } - - } else { - try { - // Write to a byte array (to be converted to a string later) - os = new ByteArrayOutputStream(); - MaryClient.Voice voice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); - String voiceName = voice != null ? voice.name() : null; - String locale = voice != null ? voice.getLocale().toString() : null; - processor.process(inputText.getText(), - ((MaryClient.DataType)cbInputType.getSelectedItem()).name(), - outputType.name(), - locale, - null, - voiceName, - "", - getAudioEffectsString(), - null, - os); - - try { - setOutputText(((ByteArrayOutputStream)os).toString("UTF-8")); - } catch (UnsupportedEncodingException uee) { - uee.printStackTrace(); - } - bEdit.setEnabled(true); - } catch (Exception e) { - e.printStackTrace(); - showErrorMessage(e.getClass().getName(), e.getMessage()); - } - } - } - - private void editOutput() { - MaryClient.DataType type = (MaryClient.DataType) cbOutputType.getSelectedItem(); - if (type == null || !type.isTextType() || !type.isInputType()) - return; - setInputText(outputText.getText()); - setOutputText(""); - // We need to make sure the item handler doesn't try to replace - // the input with a default example: - if (cbInputType.getSelectedItem().equals(cbOutputType.getSelectedItem())) { - // No problem, type won't change anyway - } else { - // Signal to the item handler that we don't want replacement - doReplaceInput = false; - cbInputType.setSelectedItem(cbOutputType.getSelectedItem()); - } - } - - private void compareTexts() { - // Only try to compare if both are MaryXML and non-empty: - if (!((MaryClient.DataType)cbOutputType.getSelectedItem()).isTextType() || - inputText.getText().length() == 0 || - outputText.getText().length() == 0) { - return; - } - try { - // First, make both documents plain text: - makeTextPlain(inputText.getStyledDocument()); - makeTextPlain(outputText.getStyledDocument()); - - // Now, highlight text in both documents: - highlightText(inputText.getStyledDocument()); - highlightText(outputText.getStyledDocument()); - - // Define text attributes for added/removed chunks: - SimpleAttributeSet removed = new SimpleAttributeSet(); - SimpleAttributeSet added = new SimpleAttributeSet(); - StyleConstants.setBold(removed, true); - StyleConstants.setBold(added, true); - StyleConstants.setItalic(removed, true); - StyleConstants.setItalic(added, true); - StyleConstants.setUnderline(added, true); - StyleConstants.setForeground(removed, Color.red); - StyleConstants.setForeground(added, Color.green.darker()); - // Calculate the differences between input and output: - String input = inputText.getStyledDocument().getText(0, inputText.getStyledDocument().getLength()); - String[] inputWords = MaryUtils.splitIntoSensibleXMLUnits(input); - int[] inputIndex = new int[inputWords.length+1]; - int total = 0; - for (int i=0; i diffs = new Diff(inputWords, outputWords).diff(); - for (Difference diff : diffs) { - int delStart = diff.getDeletedStart(); - int delEnd = diff.getDeletedEnd(); - int addStart = diff.getAddedStart(); - int addEnd = diff.getAddedEnd(); - if (delEnd != Difference.NONE) { - inputText.getStyledDocument().setCharacterAttributes(inputIndex[delStart], inputIndex[delEnd+1]-inputIndex[delStart], removed, false); - //System.err.println("deleted "+delStart+"-"+(delEnd+1)+": [" + input.substring(inputIndex[delStart], inputIndex[delEnd+1]) + "] / [" + inputText.getStyledDocument().getText(inputIndex[delStart], inputIndex[delEnd+1]-inputIndex[delStart]) + "]"); - } - if (addEnd != Difference.NONE) { - outputText.getStyledDocument().setCharacterAttributes(outputIndex[addStart], outputIndex[addEnd+1]-outputIndex[addStart], added, false); - //System.err.println("added "+addStart+"-"+(addEnd+1)+": [" + output.substring(outputIndex[addStart], outputIndex[addEnd+1]) + "] / [" + outputText.getStyledDocument().getText(outputIndex[addStart], outputIndex[addEnd+1]-outputIndex[addStart]) + "]"); - } - } - } catch(Exception ex) { ex.printStackTrace(); } - } - - protected void setInputText(String text) - { - inputText.setText(text); - makeTextPlain(inputText.getStyledDocument()); - inputText.setCaretPosition(0); - } - - protected void setOutputText(String text) - { - outputText.setText(text); - makeTextPlain(outputText.getStyledDocument()); - outputText.setCaretPosition(0); - } - - private MaryClient.Voice getPrevVoice() { return prevVoice; } - private void setPrevVoice(MaryClient.Voice prevVoice) { - this.prevVoice = prevVoice; - } - - public void resetPlayButton() - { - bPlay.setText("Play"); - if (audioPlayer != null) { - audioPlayer.cancel(); - audioPlayer = null; - } - } - - protected void showErrorMessage(String title, String message) - { - JOptionPane.showMessageDialog(this, - message + - "\n\nIf you think this is a bug in the MARY system,\n" + - "please help improve the system by filing a bug report\n" + - "on the MARY development page: \n" + - "http://mary.opendfki.de/newticket\n", - title, - JOptionPane.ERROR_MESSAGE); - - } - - public static void main(String[] args) throws Exception - { - mainFrame = new JFrame("Mary GUI Client"); - mainFrame.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) {System.exit(0);} - }); - MaryGUIClient m = new MaryGUIClient(); - mainFrame.setContentPane(m); - mainFrame.pack(); - mainFrame.setVisible(true); - - } - - class MaryGUIFocusTraversalPolicy - extends FocusTraversalPolicy { - - public Component getComponentAfter(Container focusCycleRoot, - Component aComponent) - { - if (aComponent.equals(cbInputType)) { - return cbOutputType; - } else if (aComponent.equals(cbOutputType)) { - return cbDefaultVoice; - } else if (aComponent.equals(cbDefaultVoice)) { - if (cbVoiceExampleText.isVisible()){ - return cbVoiceExampleText; - } else { - return inputText; - } - } else if (aComponent.equals(cbVoiceExampleText)) { - return inputText; - } else if (aComponent.equals(inputText)) { - if (audioPanel.isVisible()){ - return bPlay; - } else { - return bProcess; - } - } else if (aComponent.equals(bProcess)) { - if (bEdit.isEnabled()){ - return bEdit; - } else { - if (allowSave && bSaveOutput.isEnabled()){ - return bSaveOutput; - } else { - return cbInputType; - } - } - } else if (aComponent.equals(bPlay)) { - if (allowSave){ - return bSaveOutput; - } else { - return cbInputType; - } - } else if (aComponent.equals(outputText)) { - if (bEdit.isEnabled()){ - return bEdit; - } else { - return cbInputType; - } - } else if (aComponent.equals(bEdit)) { - return bCompare; - } else if (aComponent.equals(bCompare)) { - if (allowSave){ - return bSaveOutput; - } else { - return cbInputType; - } - } else if (aComponent.equals(bSaveOutput)) { - return cbInputType; - } - return cbInputType; - } - - public Component getComponentBefore(Container focusCycleRoot, - Component aComponent) - { - if (aComponent.equals(bSaveOutput)) { - if (!buttonPanel.isVisible()){ - - return bPlay; - } else { - if (bCompare.isEnabled()){ - - return bCompare; - } else { - - return bProcess; - } - } - } else if (aComponent.equals(bCompare)) { - return bEdit; - } else if (aComponent.equals(bEdit)) { - return bProcess; - } else if (aComponent.equals(outputText)) { - return bProcess; - } else if (aComponent.equals(bPlay)) { - return inputText; - } else if (aComponent.equals(bProcess)) { - return inputText; - } else if (aComponent.equals(inputText)) { - if (cbVoiceExampleText.isVisible()){ - return cbVoiceExampleText; - } else { - return cbDefaultVoice; - } - } else if (aComponent.equals(cbVoiceExampleText)) { - return cbDefaultVoice; - } else if (aComponent.equals(cbDefaultVoice)) { - return cbOutputType; - } else if (aComponent.equals(cbOutputType)) { - return cbInputType; - } else if (aComponent.equals(cbInputType)) { - if (allowSave && bSaveOutput.isEnabled()){ - return bSaveOutput; - } else { - if (buttonPanel.isVisible()){ - return bProcess; - } else { - return bPlay; - } - } - } - return cbInputType; - } - - public Component getDefaultComponent(Container focusCycleRoot) - { - return cbInputType; - } - - public Component getLastComponent(Container focusCycleRoot) - { - return bSaveOutput; - } - - public Component getFirstComponent(Container focusCycleRoot) - { - return cbInputType; - } - } -} +package marytts.client; + +//General Java Classes +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.FocusTraversalPolicy; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.KeyboardFocusManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.KeyStroke; +import javax.swing.filechooser.FileFilter; +import javax.swing.text.BadLocationException; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledDocument; + +import marytts.client.http.MaryHttpClient; +import marytts.util.MaryUtils; +import marytts.util.http.Address; +import marytts.util.io.SimpleFileFilter; + +import org.incava.util.diff.Diff; +import org.incava.util.diff.Difference; + + + + +/** + * A GUI Interface to the Mary Client, allowing to access and modify + * intermediate processing results. + * @author Marc.Schroeder, oytun.turk + * @see MaryHttpClient The client implementation + */ + +public class MaryGUIClient extends JPanel +{ + + /* -------------------- GUI stuff -------------------- */ + + private Dimension paneDimension; + // Input + private JPanel inputTypePanel; + private JComboBox cbInputType; + private JPanel inputPanel; + private JScrollPane inputScrollPane; + private JTextPane inputText; + private JPanel voicePanel; + private JComboBox cbDefaultVoice; + private JComboBox cbVoiceExampleText; + private boolean doReplaceInput = true; + // When the user changes input type, he is offered an example text for + // the new input type. In order to prevent this when setting a new input + // type from within the program, doReplaceInput must be set to false + // before triggering the selection changed event. + + // Output + private boolean showingTextOutput = true; + private JPanel outputTypePanel; + private JComboBox cbOutputType; + private JButton bSaveOutput; + private JTextPane outputText; + private JScrollPane outputScrollPane; + private JPanel audioPanel; + private JButton bPlay; + private JPanel savePanel; + + //Audio effects + private boolean isButtonHide = true; + private boolean showingAudioEffects = false; + private JPanel showHidePanel; + private JButton showHideEffects; + private JList effectsList; + private AudioEffectsBoxGUI effectsBox; + private String [] effectNames; + private String [] exampleParams; + private String [] helpTexts; + // + + // Processing Buttons + private JPanel buttonPanel; + private JButton bProcess; + private JButton bEdit; + private JButton bCompare; + + static JFrame mainFrame; + static JApplet mainApplet; + + /* -------------------- Data and Processing stuff -------------------- */ + private MaryClient processor; + + private marytts.util.data.audio.AudioPlayer audioPlayer = null; + private boolean allowSave; + private boolean streamMp3 = false; + private MaryClient.Voice prevVoice = null; + + //Map of limited Domain Voices and their example Texts + private Map> limDomVoices = new HashMap>(); + + private GridBagLayout gridBagLayout; + private GridBagConstraints gridC; + + static FocusTraversalPolicy maryGUITraversal; + + /** + * Create a MaryGUIClient instance that connects to the server host + * and port as specified in the system properties "server.host" and "server.port", + * which default to "cling.dfki.uni-sb.de" and 59125, respectively. + * @throws IOException + * @throws UnknownHostException + */ + public MaryGUIClient() throws Exception + { + super(); + // First the MaryHttpClient processor class, because it may provide + // information needed in the GUI creation. + try { + processor = MaryClient.getMaryClient(); + streamMp3 = Boolean.getBoolean("stream.mp3"); + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(null, + e.getMessage(), + "Cannot connect to server", + JOptionPane.ERROR_MESSAGE); + System.exit(1); + } + allowSave = true; + init(); + } + + /** + * Create a MaryGUIClient instance that connects to the given server host + * and port. This is meant to be used from Applets. + * @param host + * @param port + * @throws IOException + * @throws UnknownHostException + */ + public MaryGUIClient(Address hostAddress, JApplet applet) throws IOException + { + super(); + // First the MaryHttpClient processor class, because it may provide + // information needed in the GUI creation. + try { + processor = new MaryHttpClient(hostAddress, false, false); + } catch (Exception e) { + System.out.println("Problem creating mary client"); + e.printStackTrace(); + JOptionPane.showMessageDialog(null, + e.getMessage(), + "Cannot connect to server", + JOptionPane.ERROR_MESSAGE); + System.exit(1); + } + mainApplet = applet; + allowSave = false; + init(); + } + + /** + * Create an instance of the MaryHttpClient class which does the processing, + * and initialise the GUI. + * @throws InterruptedException + * @throws IOException + * @throws Exception + */ + public void init() throws IOException + { + maryGUITraversal = new MaryGUIFocusTraversalPolicy(); + //if this is a normal gui + if (mainFrame != null){ + mainFrame.setFocusTraversalPolicy(maryGUITraversal); + } else { //this is an applet + mainApplet.setFocusTraversalPolicy(maryGUITraversal); + } + + paneDimension = new Dimension(250,400); + // Layout + gridBagLayout = new GridBagLayout(); + gridC = new GridBagConstraints(); + + gridC.insets = new Insets( 2,2,2,2 ); + gridC.weightx = 0.1; + gridC.weighty = 0.1; + setLayout(gridBagLayout); + + //////////////// Left Column: Input ///////////////////// + // Input type + inputTypePanel = new JPanel(); + inputTypePanel.setLayout(new FlowLayout(FlowLayout.LEADING)); + gridC.gridx = 0; + gridC.gridy = 0; + gridC.gridwidth = 3; + gridC.fill = GridBagConstraints.HORIZONTAL; + gridBagLayout.setConstraints( inputTypePanel, gridC ); + add( inputTypePanel ); + gridC.gridwidth = 1; + JLabel inputTypeLabel = new JLabel( "Input Type: " ); + inputTypePanel.add(inputTypeLabel); + assert processor.getInputDataTypes().size() > 0; + assert processor.getOutputDataTypes().size() > 0; + cbInputType = new JComboBox( processor.getInputDataTypes() ); + cbInputType.setName("Input Type"); + cbInputType.getAccessibleContext().setAccessibleName("Input Type selection"); + cbInputType.setToolTipText( "Specify the type of data contained " + + "in the input text area below." ); + cbInputType.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + verifyExamplesVisible(); + if (doReplaceInput) { + setExampleInputText(); + } else { + // input text was set by other code + doReplaceInput = true; + } + //setOutputTypeItems(); + } + } + }); + inputTypePanel.add( cbInputType ); + + //Input Text area + inputPanel = new JPanel(); + inputPanel.setLayout(new BoxLayout(inputPanel, BoxLayout.Y_AXIS)); + inputPanel.setMinimumSize(paneDimension); + inputPanel.setPreferredSize(paneDimension); + gridC.gridx = 0; + gridC.gridy = 1; + gridC.gridwidth = 3; + gridC.gridheight = 3; + gridC.weightx = 0.4; + gridC.weighty = 0.8; + //gridC.ipadx = 270; + //gridC.ipady = 200; + gridC.fill = GridBagConstraints.BOTH; + gridBagLayout.setConstraints( inputPanel, gridC ); + add( inputPanel ); + gridC.gridwidth = 1; + gridC.gridheight = 1; + gridC.weightx = 0.1; + gridC.weighty = 0.1; + gridC.ipadx = 0; + gridC.ipady = 0; + gridC.fill = GridBagConstraints.NONE; + inputText = new JTextPane(); + + inputText.getAccessibleContext().setAccessibleName("Input Text Area"); + + //Set Tab and Shift-Tab for Keyboard movement + Set forwardKeys = new HashSet(); + forwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0, false)); + inputText.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,forwardKeys); + Set backwardKeys = new HashSet(); + backwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,KeyEvent.SHIFT_MASK+KeyEvent.SHIFT_DOWN_MASK, false)); + inputText.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,backwardKeys); + + inputScrollPane = new JScrollPane(inputText); + inputPanel.add(inputScrollPane); + inputScrollPane.setPreferredSize(new Dimension(inputPanel.getPreferredSize().width, 1000)); + //example text for limDom voices + cbVoiceExampleText = new JComboBox(); + cbVoiceExampleText.setName("Example Text"); + cbVoiceExampleText.getAccessibleContext().setAccessibleName("Example text selection"); + cbVoiceExampleText.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + if (doReplaceInput + && ((MaryClient.DataType)cbInputType.getSelectedItem()).name().startsWith("TEXT")) + setInputText((String)cbVoiceExampleText.getSelectedItem()); + } + } + }); + cbVoiceExampleText.setPreferredSize(new Dimension(inputPanel.getPreferredSize().width, 25)); + inputPanel.add(cbVoiceExampleText); + + // Select voice + voicePanel = new JPanel(); + voicePanel.setLayout(new FlowLayout(FlowLayout.LEADING)); + gridC.gridx = 0; + gridC.gridy = 4; + gridC.gridwidth = 4; + gridC.gridheight = 2; + gridC.fill = GridBagConstraints.HORIZONTAL; + gridBagLayout.setConstraints( voicePanel, gridC ); + add( voicePanel ); + gridC.gridwidth = 1; + gridC.gridheight = 1; + JLabel voiceLabel = new JLabel("Voice:"); + voicePanel.add( voiceLabel ); + cbDefaultVoice = new JComboBox(); + cbDefaultVoice.setName("Voice selection"); + cbDefaultVoice.getAccessibleContext().setAccessibleName("Voice selection"); + voicePanel.add( cbDefaultVoice ); + cbDefaultVoice.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + fillExampleTexts(); + verifyExamplesVisible(); + MaryClient.Voice voice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); + MaryClient.DataType dataType = (MaryClient.DataType)cbInputType.getSelectedItem(); + if (doReplaceInput + && (voice.isLimitedDomain() && dataType.name().startsWith("TEXT") + || getPrevVoice() == null + || !getPrevVoice().getLocale().equals(voice.getLocale()))) + setExampleInputText(); + setPrevVoice(voice); + + updateAudioEffects(); + } + } + }); + + // For the limited domain voices, get example texts: + Vector voices = processor.getVoices(); + if (voices != null) { + for (MaryClient.Voice v : voices) { + if (v.isLimitedDomain()){ + limDomVoices.put(v.name(), processor.getVoiceExampleTextsLimitedDomain(v.name())); + } + } + } + + verifyDefaultVoices(); + fillExampleTexts(); + verifyExamplesVisible(); + setExampleInputText(); + + //////////////// Centre Column: Buttons ///////////////////// + // Action buttons in centre + buttonPanel = new JPanel(); + buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS)); + gridC.gridx = 3; + gridC.gridy = 1; + gridC.gridheight = 3; + gridC.fill = GridBagConstraints.BOTH; + gridBagLayout.setConstraints( buttonPanel, gridC ); + add( buttonPanel ); + bProcess = new JButton( "Process ->" ); + bProcess.setToolTipText( "Call the Mary Server." + + "The input will be transformed into the specified output type." ); + bProcess.getAccessibleContext().setAccessibleName("Process button"); + bProcess.setActionCommand( "process" ); + bProcess.setMnemonic('P'); + bProcess.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + processInput(); + verifyEnableButtons(); + } + }); + buttonPanel.add(Box.createVerticalGlue()); + buttonPanel.add( bProcess ); + bProcess.setAlignmentX(Component.CENTER_ALIGNMENT); + buttonPanel.add(Box.createVerticalGlue()); + + bEdit = new JButton( "<- Edit" ); + bEdit.setToolTipText( "Edit the content of the output text area as the new input." + + " The current content of the input text area will be discarded." ); + bEdit.getAccessibleContext().setAccessibleName("Edit button"); + bEdit.setActionCommand( "edit" ); + bEdit.setMnemonic('E'); + bEdit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editOutput(); + verifyEnableButtons(); + } + }); + buttonPanel.add( bEdit ); + bEdit.setAlignmentX(Component.CENTER_ALIGNMENT); + buttonPanel.add(Box.createVerticalGlue()); + + bCompare = new JButton( "<- Compare ->" ); + bCompare.setToolTipText( "Compare input and output" + + "(available only if both are MaryXML types)." ); + bCompare.getAccessibleContext().setAccessibleName("Compare button"); + bCompare.setActionCommand( "compare" ); + bCompare.setMnemonic('C'); + bCompare.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + compareTexts(); + verifyEnableButtons(); + } + }); + buttonPanel.add( bCompare ); + bCompare.setAlignmentX(Component.CENTER_ALIGNMENT); + buttonPanel.add(Box.createVerticalGlue()); + buttonPanel.setPreferredSize(new Dimension(buttonPanel.getPreferredSize().width, paneDimension.height)); + + //////////////// Right Column: Output ///////////////////// + // Output type + outputTypePanel = new JPanel(); + outputTypePanel.setLayout(new FlowLayout(FlowLayout.TRAILING)); + gridC.gridx = 4; + gridC.gridy = 0; + gridC.gridwidth = 3; + gridC.gridheight = 1; + gridC.ipady = 10; + gridC.fill = GridBagConstraints.HORIZONTAL; + gridBagLayout.setConstraints( outputTypePanel, gridC ); + add( outputTypePanel ); + gridC.ipady = 0; + gridC.gridwidth = 1; + JLabel outputTypeLabel = new JLabel( "Output Type: " ); + outputTypePanel.add( outputTypeLabel ); + cbOutputType = new JComboBox(); + cbOutputType.setName("Output type"); + cbOutputType.getAccessibleContext().setAccessibleName("Output type selection"); + setOutputTypeItems(); + // The last possible output type (= audio) is the default + // output type: + cbOutputType.setSelectedIndex(cbOutputType.getItemCount() - 1); + cbOutputType.setToolTipText( "Specify the output type for the next " + + "processing action (Process button)." ); + cbOutputType.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + if (e.getStateChange() == ItemEvent.SELECTED) { + verifyOutputDisplay(); + verifyEnableButtons(); + revalidate(); + } + } + }); + outputTypePanel.add( cbOutputType ); + + // Output Text area + if (((MaryClient.DataType)cbOutputType.getSelectedItem()).isTextType()) + showingTextOutput = true; + else + showingTextOutput = false; + outputText = new JTextPane(); + outputText.getAccessibleContext().setAccessibleName("Output text"); + + //set tab and shift-tab for keyboard movement + outputText.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,forwardKeys); + outputText.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,backwardKeys); + + // outputText.setLineWrap(false); + outputText.setEditable(false); + outputScrollPane = new JScrollPane(outputText); + outputScrollPane.setMinimumSize(paneDimension); + outputScrollPane.setPreferredSize(paneDimension); + gridC.gridx = 4; + gridC.gridy = 1; + gridC.gridwidth = 3; + gridC.gridheight = 3; + gridC.weightx = 0.4; + gridC.weighty = 0.8; + gridC.fill = GridBagConstraints.BOTH; + gridBagLayout.setConstraints(outputScrollPane, gridC); + if (!showingTextOutput) + outputScrollPane.setVisible(false); + add( outputScrollPane ); + + //Audio effects + setAudioEffects(); + + isButtonHide = false; + if (effectsBox.hasEffects()) + { + gridC.gridx = 4; + gridC.gridy = 1; + gridC.gridwidth = 3; + gridC.gridheight = 3; + gridC.weightx = 0.1; + gridC.weighty = 0.1; + gridC.ipadx = 0; + gridC.ipady = 0; + gridC.fill = GridBagConstraints.BOTH; + gridBagLayout.setConstraints(effectsBox.mainPanel, gridC); + + add(effectsBox.mainPanel); + + updateAudioEffects(); + + if (effectsBox!=null && effectsBox.mainPanel!=null) + { + showHidePanel = new JPanel(); + showHidePanel.setPreferredSize(paneDimension); + showHidePanel.setLayout( new BoxLayout(showHidePanel, BoxLayout.Y_AXIS) ); + + if (!showingTextOutput) + { + showHideEffects = new JButton("Hide Effects"); + isButtonHide = true; + } + else + { + showHideEffects = new JButton("Show Effects"); + isButtonHide = false; + } + + showHideEffects.setToolTipText( "Hide or show available audio effects for post-processing the TTS output" ); + showHideEffects.getAccessibleContext().setAccessibleName("Hide/Show audio effects button"); + + showHideEffects.addActionListener( new ActionListener() { + public void actionPerformed(ActionEvent e) { + showHideEffectAction(); + } + }); + + showHidePanel.add(Box.createVerticalGlue()); + showHidePanel.add(showHideEffects); + showHidePanel.add(Box.createVerticalGlue()); + showHideEffects.setAlignmentX(Component.CENTER_ALIGNMENT); + + gridC.gridx = 4; + if (!showingTextOutput) + gridC.gridy = 4; + else + gridC.gridy = 3; + + gridC.gridwidth = 3; + gridC.gridheight = 1; + gridC.ipady = 10; + gridC.fill = GridBagConstraints.BOTH; + gridBagLayout.setConstraints(showHidePanel, gridC); + add(showHidePanel); + gridC.ipady = 0; + + if (effectsBox.mainPanel!=null) + { + if (!showingTextOutput && isButtonHide) + { + effectsBox.mainPanel.setVisible(true); + showingAudioEffects = true; + } + else + { + effectsBox.mainPanel.setVisible(false); + showingAudioEffects = false; + } + } + } + } + // + + gridC.gridwidth = 1; + gridC.gridheight = 1; + gridC.weightx = 0.1; + gridC.weighty = 0.1; + gridC.ipadx = 0; + gridC.ipady = 0; + gridC.fill = GridBagConstraints.NONE; + + // Overlapping location: Audio play button + audioPanel = new JPanel(); + audioPanel.setPreferredSize(paneDimension); + audioPanel.setLayout( new BoxLayout(audioPanel, BoxLayout.Y_AXIS) ); + bPlay = new JButton( "Play" ); + bPlay.setToolTipText( "Synthesize and play the resulting audio stream." ); + bPlay.getAccessibleContext().setAccessibleName("Play button"); + bPlay.setActionCommand( "play" ); + bPlay.setMnemonic('P'); + bPlay.addActionListener( new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (audioPlayer != null) { // an audioPlayer is currently playing + audioPlayer.cancel(); + audioPlayer = null; + bPlay.setText("Play"); + } else { + processInput(); + } + } + }); + audioPanel.add(Box.createVerticalGlue()); + audioPanel.add(bPlay); + audioPanel.add(Box.createVerticalGlue()); + bPlay.setAlignmentX(Component.CENTER_ALIGNMENT); + //bPlay.setMaximumSize(bPlay.getPreferredSize()); + + if (showingTextOutput) + audioPanel.setVisible(false); + gridC.gridx = 4; + if (showingAudioEffects) + gridC.gridy = 5; + else + gridC.gridy = 4; + gridC.gridwidth = 3; + gridC.gridheight = 1; + gridC.ipady = 10; + gridC.fill = GridBagConstraints.BOTH; + gridBagLayout.setConstraints(audioPanel, gridC); + add( audioPanel ); + gridC.gridwidth = 1; + gridC.ipady = 0; + + // Output Save button + if (allowSave) { + savePanel = new JPanel(); + savePanel.setLayout(new FlowLayout(FlowLayout.TRAILING)); + gridC.gridx = 4; + gridC.ipady = 10; + if (showingAudioEffects) + gridC.gridy = 6; + else + gridC.gridy = 5; + + gridC.fill = GridBagConstraints.HORIZONTAL; + gridBagLayout.setConstraints( savePanel, gridC ); + add(savePanel); + ImageIcon saveIcon = new ImageIcon("save.gif"); + bSaveOutput = new JButton( "Save...", saveIcon ); + bSaveOutput.setToolTipText( "Save the output as a file." ); + bSaveOutput.getAccessibleContext().setAccessibleName("Save Output button"); + bSaveOutput.setActionCommand( "saveOutput" ); + bSaveOutput.setMnemonic('S'); + bSaveOutput.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + saveOutput(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } catch (InterruptedException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + }); + savePanel.add( bSaveOutput ); + gridC.ipady = 0; + } + setPreferredSize(new Dimension(720,480)); + + verifyEnableButtons(); + cbInputType.requestFocusInWindow(); + + showHideEffectAction(); + } + + private void setAudioEffects() + { + String availableAudioEffects = ""; + String strLineBreak = ""; + + try { + availableAudioEffects = processor.getAudioEffects(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + effectsBox = new AudioEffectsBoxGUI(availableAudioEffects); + // TODO: this is overkill, we could load a help text when the + // user presses a help button, but it would require re-engineering the code a bit. + // fill help through separate queries: + for (int i=0; i< effectsBox.getData().getTotalEffects(); i++) { + AudioEffectControlData eff = effectsBox.getData().getControlData(i); + try { + eff.setHelpText(processor.requestEffectHelpText(eff.getEffectName())); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + + private void showHideEffectAction() + { + if (isButtonHide) + { + if (effectsBox!=null && effectsBox.mainPanel!=null) + effectsBox.mainPanel.setVisible(false); + + if (showHideEffects!=null) + showHideEffects.setText("Show Effects"); + + isButtonHide = false; + showingAudioEffects = false; + } + else + { + if (effectsBox!=null && effectsBox.mainPanel!=null) + effectsBox.mainPanel.setVisible(true); + + if (showHideEffects!=null) + showHideEffects.setText("Hide Effects"); + + isButtonHide = true; + showingAudioEffects = true; + } + } + + //If there are any effects available for the selected voice + // update audio effects box accordingly + private void updateAudioEffects() + { + //Overlapping location: Audio effects box + //Initialize the effects here (normally using info from the server) + if (effectsBox != null) + { + if (effectsBox.hasEffects() && effectsBox.getData().getTotalEffects()>0) + { + MaryClient.Voice voice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); + if (voice == null) return; + + for (int i=0; i 0) effects.append("+"); + effects.append(name); + if (params != null && params.length()>0) { + effects.append("(").append(params).append(")"); + } + } + } + } + return effects.toString(); + } + + + + + private void setExampleInputText() + { + MaryClient.Voice defaultVoice = (MaryClient.Voice) cbDefaultVoice.getSelectedItem(); + if (defaultVoice == null) return; + MaryClient.DataType inputType = (MaryClient.DataType) cbInputType.getSelectedItem(); + if (defaultVoice.isLimitedDomain() && inputType.name().startsWith("TEXT")) { + setInputText((String) cbVoiceExampleText.getSelectedItem()); + } else { + try { + String exampleText = processor.getServerExampleText(inputType.name(), defaultVoice.getLocale().toString()); + setInputText(exampleText); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void fillExampleTexts() + { + MaryClient.Voice defaultVoice = (MaryClient.Voice) cbDefaultVoice.getSelectedItem(); + if (defaultVoice == null || !defaultVoice.isLimitedDomain()) return; + Vector sentences = (Vector)limDomVoices.get(defaultVoice.name()); + assert sentences != null; + cbVoiceExampleText.removeAllItems(); + for (int i = 0; i 0) { + bCompare.setEnabled(true); + } else { + bCompare.setEnabled(false); + } + } + + + /** + * Verify that the list of voices in cbDefaultVoices matches the language of the input format. + * @throws InterruptedException + * @throws IOException + */ + private void verifyDefaultVoices() throws IOException + { + MaryClient.DataType inputType = (MaryClient.DataType)cbInputType.getSelectedItem(); + // Is the default voice still suitable for the input locale? + MaryClient.Voice defaultVoice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); + // Reset the list, just in case + cbDefaultVoice.removeAllItems(); + Vector voices = processor.getVoices(); + if (voices != null) { + for (MaryClient.Voice v : processor.getVoices()) { + cbDefaultVoice.addItem(v); + } + if (defaultVoice != null) { + cbDefaultVoice.setSelectedItem(defaultVoice); + } else { // First in list is default voice: + cbDefaultVoice.setSelectedIndex(0); + } + } + } + + + + private void setOutputTypeItems() throws IOException + { + MaryClient.DataType inputType = (MaryClient.DataType) cbInputType.getSelectedItem(); + MaryClient.DataType selectedItem = (MaryClient.DataType) cbOutputType.getSelectedItem(); + cbOutputType.removeAllItems(); + for (MaryClient.DataType d : processor.getOutputDataTypes()) { + cbOutputType.addItem(d); + } + cbOutputType.setSelectedItem(selectedItem); + } + + private void verifyOutputDisplay() + { + if (((MaryClient.DataType)cbOutputType.getSelectedItem()).isTextType()) + { + setOutputText(""); // erase the output text + if (!showingTextOutput) + { + // showing Audio Output + // need to change output display + audioPanel.setVisible(false); + + if (effectsBox!=null) + { + if (effectsBox.mainPanel!=null) + effectsBox.mainPanel.setVisible(false); + + if (showHidePanel!=null) + showHidePanel.setVisible(false); + } + + outputScrollPane.setVisible(true); + showingTextOutput = true; + revalidate(); + } + } + else + { // Audio output + if (showingTextOutput) + { + // change output display + outputScrollPane.setVisible(false); + audioPanel.setVisible(true); + + if (effectsBox!=null && effectsBox.mainPanel!=null) + { + if (showHidePanel!=null) + showHidePanel.setVisible(true); + + if (effectsBox.mainPanel!=null && isButtonHide) + effectsBox.mainPanel.setVisible(true); + } + + showingTextOutput = false; + revalidate(); + } + } + } + + + /* -------------------- Processing callers -------------------- */ + private File lastDirectory = null; + private String lastExtension = null; + private void saveOutput() throws IOException, InterruptedException + { + if (!allowSave) return; + try { + if (showingTextOutput) { + JFileChooser fc = new JFileChooser(); + if (lastDirectory != null) { + fc.setCurrentDirectory(lastDirectory); + } + int returnVal = fc.showSaveDialog(this); + if (returnVal == JFileChooser.APPROVE_OPTION) { + File saveFile = fc.getSelectedFile(); + lastDirectory = saveFile.getParentFile(); + PrintWriter w = new PrintWriter(new FileWriter(saveFile)); + w.print(outputText.getText()); + w.close(); + } + } else { // audio data + JFileChooser fc = new JFileChooser(); + if (lastDirectory != null) { + fc.setCurrentDirectory(lastDirectory); + } + Vector knownAudioTypes = processor.getAudioFileFormatTypes(); + String[] extensions = new String[knownAudioTypes.size()]; + String[] typeNames = new String[knownAudioTypes.size()]; + FileFilter defaultFilter = null; + for (int i=0; i to bold. + * This is "dumb", i.e. it will not try to analyse the contents of + * tags, and fail at situations like , where i would + * be printed in bold as well. + */ + private void highlightText(StyledDocument doc) { + SimpleAttributeSet highlighted = new SimpleAttributeSet(); + StyleConstants.setBold(highlighted, true); + boolean insideTag = false; + int beginText = -1; // will contain beginning of text to be highlighted + for (int i=0; i') + insideTag = false; + } else { // not inside a tag + if (c == '<') { + // Start of new tag + if (beginText != -1) { // anything to highlight? + // highlight it + doc.setCharacterAttributes(beginText, i-beginText, + highlighted, false); + beginText = -1; + } + insideTag = true; + } else { // normal text character + if (beginText == -1) { + // This is the first text character + beginText = i; + } + } + } + } // for all characters in document + // Any text at the very end of the document? + if (beginText != -1) { + doc.setCharacterAttributes(beginText, doc.getLength()-beginText, + highlighted, false); + } + } + + // Call the mary client + private void processInput() + { + OutputStream os; + MaryClient.DataType outputType = (MaryClient.DataType)cbOutputType.getSelectedItem(); + if (outputType.name().equals("AUDIO")) { + try { + audioPlayer = new marytts.util.data.audio.AudioPlayer(); + processor.streamAudio(inputText.getText(), + ((MaryClient.DataType)cbInputType.getSelectedItem()).name(), + ((MaryClient.Voice)cbDefaultVoice.getSelectedItem()).getLocale().toString(), + streamMp3 ? "MP3":"AU", + ((MaryClient.Voice)cbDefaultVoice.getSelectedItem()).name(), + "", + getAudioEffectsString(), + audioPlayer, + new MaryHttpClient.AudioPlayerListener() { + public void playerFinished() + { + resetPlayButton(); + } + public void playerException(Exception e) + { + showErrorMessage(e.getClass().getName(), e.getMessage()); + resetPlayButton(); + } + }); + bPlay.setText("Stop"); + } catch (Exception e) { + e.printStackTrace(); + showErrorMessage(e.getClass().getName(), e.getMessage()); + resetPlayButton(); + } + + } else { + try { + // Write to a byte array (to be converted to a string later) + os = new ByteArrayOutputStream(); + MaryClient.Voice voice = (MaryClient.Voice)cbDefaultVoice.getSelectedItem(); + String voiceName = voice != null ? voice.name() : null; + String locale = voice != null ? voice.getLocale().toString() : null; + processor.process(inputText.getText(), + ((MaryClient.DataType)cbInputType.getSelectedItem()).name(), + outputType.name(), + locale, + null, + voiceName, + "", + getAudioEffectsString(), + null, + os); + + try { + setOutputText(((ByteArrayOutputStream)os).toString("UTF-8")); + } catch (UnsupportedEncodingException uee) { + uee.printStackTrace(); + } + bEdit.setEnabled(true); + } catch (Exception e) { + e.printStackTrace(); + showErrorMessage(e.getClass().getName(), e.getMessage()); + } + } + } + + private void editOutput() { + MaryClient.DataType type = (MaryClient.DataType) cbOutputType.getSelectedItem(); + if (type == null || !type.isTextType() || !type.isInputType()) + return; + setInputText(outputText.getText()); + setOutputText(""); + // We need to make sure the item handler doesn't try to replace + // the input with a default example: + if (cbInputType.getSelectedItem().equals(cbOutputType.getSelectedItem())) { + // No problem, type won't change anyway + } else { + // Signal to the item handler that we don't want replacement + doReplaceInput = false; + cbInputType.setSelectedItem(cbOutputType.getSelectedItem()); + } + } + + private void compareTexts() { + // Only try to compare if both are MaryXML and non-empty: + if (!((MaryClient.DataType)cbOutputType.getSelectedItem()).isTextType() || + inputText.getText().length() == 0 || + outputText.getText().length() == 0) { + return; + } + try { + // First, make both documents plain text: + makeTextPlain(inputText.getStyledDocument()); + makeTextPlain(outputText.getStyledDocument()); + + // Now, highlight text in both documents: + highlightText(inputText.getStyledDocument()); + highlightText(outputText.getStyledDocument()); + + // Define text attributes for added/removed chunks: + SimpleAttributeSet removed = new SimpleAttributeSet(); + SimpleAttributeSet added = new SimpleAttributeSet(); + StyleConstants.setBold(removed, true); + StyleConstants.setBold(added, true); + StyleConstants.setItalic(removed, true); + StyleConstants.setItalic(added, true); + StyleConstants.setUnderline(added, true); + StyleConstants.setForeground(removed, Color.red); + StyleConstants.setForeground(added, Color.green.darker()); + // Calculate the differences between input and output: + String input = inputText.getStyledDocument().getText(0, inputText.getStyledDocument().getLength()); + String[] inputWords = MaryUtils.splitIntoSensibleXMLUnits(input); + int[] inputIndex = new int[inputWords.length+1]; + int total = 0; + for (int i=0; i diffs = new Diff(inputWords, outputWords).diff(); + for (Difference diff : diffs) { + int delStart = diff.getDeletedStart(); + int delEnd = diff.getDeletedEnd(); + int addStart = diff.getAddedStart(); + int addEnd = diff.getAddedEnd(); + if (delEnd != Difference.NONE) { + inputText.getStyledDocument().setCharacterAttributes(inputIndex[delStart], inputIndex[delEnd+1]-inputIndex[delStart], removed, false); + //System.err.println("deleted "+delStart+"-"+(delEnd+1)+": [" + input.substring(inputIndex[delStart], inputIndex[delEnd+1]) + "] / [" + inputText.getStyledDocument().getText(inputIndex[delStart], inputIndex[delEnd+1]-inputIndex[delStart]) + "]"); + } + if (addEnd != Difference.NONE) { + outputText.getStyledDocument().setCharacterAttributes(outputIndex[addStart], outputIndex[addEnd+1]-outputIndex[addStart], added, false); + //System.err.println("added "+addStart+"-"+(addEnd+1)+": [" + output.substring(outputIndex[addStart], outputIndex[addEnd+1]) + "] / [" + outputText.getStyledDocument().getText(outputIndex[addStart], outputIndex[addEnd+1]-outputIndex[addStart]) + "]"); + } + } + } catch(Exception ex) { ex.printStackTrace(); } + } + + protected void setInputText(String text) + { + inputText.setText(text); + makeTextPlain(inputText.getStyledDocument()); + inputText.setCaretPosition(0); + } + + protected void setOutputText(String text) + { + outputText.setText(text); + makeTextPlain(outputText.getStyledDocument()); + outputText.setCaretPosition(0); + } + + private MaryClient.Voice getPrevVoice() { return prevVoice; } + private void setPrevVoice(MaryClient.Voice prevVoice) { + this.prevVoice = prevVoice; + } + + public void resetPlayButton() + { + bPlay.setText("Play"); + if (audioPlayer != null) { + audioPlayer.cancel(); + audioPlayer = null; + } + } + + protected void showErrorMessage(String title, String message) + { + JOptionPane.showMessageDialog(this, + message + + "\n\nIf you think this is a bug in the MARY system,\n" + + "please help improve the system by filing a bug report\n" + + "on the MARY development page: \n" + + "http://mary.opendfki.de/newticket\n", + title, + JOptionPane.ERROR_MESSAGE); + + } + + public static void main(String[] args) throws Exception + { + mainFrame = new JFrame("Mary GUI Client"); + mainFrame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) {System.exit(0);} + }); + MaryGUIClient m = new MaryGUIClient(); + mainFrame.setContentPane(m); + mainFrame.pack(); + mainFrame.setVisible(true); + + } + + class MaryGUIFocusTraversalPolicy + extends FocusTraversalPolicy { + + public Component getComponentAfter(Container focusCycleRoot, + Component aComponent) + { + if (aComponent.equals(cbInputType)) { + return cbOutputType; + } else if (aComponent.equals(cbOutputType)) { + return cbDefaultVoice; + } else if (aComponent.equals(cbDefaultVoice)) { + if (cbVoiceExampleText.isVisible()){ + return cbVoiceExampleText; + } else { + return inputText; + } + } else if (aComponent.equals(cbVoiceExampleText)) { + return inputText; + } else if (aComponent.equals(inputText)) { + if (audioPanel.isVisible()){ + return bPlay; + } else { + return bProcess; + } + } else if (aComponent.equals(bProcess)) { + if (bEdit.isEnabled()){ + return bEdit; + } else { + if (allowSave && bSaveOutput.isEnabled()){ + return bSaveOutput; + } else { + return cbInputType; + } + } + } else if (aComponent.equals(bPlay)) { + if (allowSave){ + return bSaveOutput; + } else { + return cbInputType; + } + } else if (aComponent.equals(outputText)) { + if (bEdit.isEnabled()){ + return bEdit; + } else { + return cbInputType; + } + } else if (aComponent.equals(bEdit)) { + return bCompare; + } else if (aComponent.equals(bCompare)) { + if (allowSave){ + return bSaveOutput; + } else { + return cbInputType; + } + } else if (aComponent.equals(bSaveOutput)) { + return cbInputType; + } + return cbInputType; + } + + public Component getComponentBefore(Container focusCycleRoot, + Component aComponent) + { + if (aComponent.equals(bSaveOutput)) { + if (!buttonPanel.isVisible()){ + + return bPlay; + } else { + if (bCompare.isEnabled()){ + + return bCompare; + } else { + + return bProcess; + } + } + } else if (aComponent.equals(bCompare)) { + return bEdit; + } else if (aComponent.equals(bEdit)) { + return bProcess; + } else if (aComponent.equals(outputText)) { + return bProcess; + } else if (aComponent.equals(bPlay)) { + return inputText; + } else if (aComponent.equals(bProcess)) { + return inputText; + } else if (aComponent.equals(inputText)) { + if (cbVoiceExampleText.isVisible()){ + return cbVoiceExampleText; + } else { + return cbDefaultVoice; + } + } else if (aComponent.equals(cbVoiceExampleText)) { + return cbDefaultVoice; + } else if (aComponent.equals(cbDefaultVoice)) { + return cbOutputType; + } else if (aComponent.equals(cbOutputType)) { + return cbInputType; + } else if (aComponent.equals(cbInputType)) { + if (allowSave && bSaveOutput.isEnabled()){ + return bSaveOutput; + } else { + if (buttonPanel.isVisible()){ + return bProcess; + } else { + return bPlay; + } + } + } + return cbInputType; + } + + public Component getDefaultComponent(Container focusCycleRoot) + { + return cbInputType; + } + + public Component getLastComponent(Container focusCycleRoot) + { + return bSaveOutput; + } + + public Component getFirstComponent(Container focusCycleRoot) + { + return cbInputType; + } + } +} diff --git a/marytts-client/src/main/java/marytts/client/MaryInterfaceApplet.java b/marytts-client/src/main/java/marytts/client/MaryInterfaceApplet.java index 5b592876..de287904 100644 --- a/marytts-client/src/main/java/marytts/client/MaryInterfaceApplet.java +++ b/marytts-client/src/main/java/marytts/client/MaryInterfaceApplet.java @@ -1,6 +1,6 @@ -/** - * Copyright 2000-2006 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. +/** + * Copyright 2000-2006 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * @@ -17,45 +17,41 @@ * along with this program. If not, see . * */ -package marytts.client; - -import java.awt.FlowLayout; -import java.io.IOException; - -import javax.swing.JApplet; - -import marytts.util.http.Address; - -/** - * @author Marc Schröder - * - */ -public class MaryInterfaceApplet extends JApplet -{ - private MaryGUIClient maryExpertInterface; - - public void init() - { - String host = getCodeBase().getHost(); - if (host == null || host.equals("")) { - host = "mary.dfki.de"; - } - System.out.println("Connecting to "+host); - int port = 59125; - try { - maryExpertInterface = new MaryGUIClient(new Address(host, port), this); - getContentPane().setLayout(new FlowLayout()); - getContentPane().add(maryExpertInterface); - } catch (IOException ioe) { - System.err.println("Cannot connect to MARY server on "+host+":"+port); - ioe.printStackTrace(); - } - } - - public void destroy() - { - - } - -} +package marytts.client; +import java.awt.FlowLayout; +import java.io.IOException; + +import javax.swing.JApplet; + +import marytts.util.http.Address; + +/** + * @author Marc Schröder + * + */ +public class MaryInterfaceApplet extends JApplet { + private MaryGUIClient maryExpertInterface; + + public void init() { + String host = getCodeBase().getHost(); + if (host == null || host.equals("")) { + host = "mary.dfki.de"; + } + System.out.println("Connecting to " + host); + int port = 59125; + try { + maryExpertInterface = new MaryGUIClient(new Address(host, port), this); + getContentPane().setLayout(new FlowLayout()); + getContentPane().add(maryExpertInterface); + } catch (IOException ioe) { + System.err.println("Cannot connect to MARY server on " + host + ":" + port); + ioe.printStackTrace(); + } + } + + public void destroy() { + + } + +} diff --git a/marytts-client/src/main/java/marytts/client/http/MaryHttpClient.java b/marytts-client/src/main/java/marytts/client/http/MaryHttpClient.java index 7b6ecbf0..b68b44ed 100644 --- a/marytts-client/src/main/java/marytts/client/http/MaryHttpClient.java +++ b/marytts-client/src/main/java/marytts/client/http/MaryHttpClient.java @@ -1,6 +1,6 @@ -/** - * Copyright 2000-2006 DFKI GmbH. - * All Rights Reserved. Use is subject to license terms. +/** + * Copyright 2000-2006 DFKI GmbH. + * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * @@ -17,605 +17,605 @@ * along with this program. If not, see . * */ -package marytts.client.http; - -// General Java Classes -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; -import java.net.UnknownHostException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.Timer; -import java.util.TimerTask; -import java.util.Vector; - -import javax.sound.sampled.AudioFileFormat; -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.AudioFormat.Encoding; - -import marytts.client.MaryClient; -import marytts.client.MaryGUIClient; -import marytts.util.http.Address; -import marytts.util.io.FileUtils; -import marytts.util.string.StringUtils; - -/** - * An HTTP client implementing the MARY protocol. - * It can be used as a command line client or from within java code. - * @author Marc Schröder, oytun.turk - * @see MaryGUIClient A GUI interface to this client - * @see marytts.server.MaryServer Description of the MARY protocol - */ - -public class MaryHttpClient extends MaryClient -{ - - /** - * The simplest way to create a mary client. It will connect to the - * MARY server running at DFKI. Only use this for testing purposes! - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public MaryHttpClient() throws IOException - { - super(); - } - - public MaryHttpClient(boolean quiet) throws IOException - { - super(quiet); - } - - /** - * The typical way to create a mary client. It will connect to the - * MARY client running at the given host and port. - * This constructor reads two system properties: - *
    - *
  • mary.client.profile (=true/false) - - * determines whether profiling (timing) information is calculated;
  • - *
  • mary.client.quiet (=true/false) - - * tells the client not to print any of the normal information to stderr.
  • - *
- * @param host the host where to contact a MARY server - * @param port the socket port where to contact a MARY server - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public MaryHttpClient(Address serverAddress) throws IOException - { - super(serverAddress); - } - - /** - * An alternative way to create a mary client, which works with applets. - * It will connect to the MARY client running at the given host and port. - * Note that in applets, the host must be the same as the one from which - * the applet was loaded; otherwise, a security exception is thrown. - * @param host the host where to contact a MARY server - * @param port the socket port where to contact a MARY server - * @param profile determines whether profiling (timing) information is calculated - * @param quiet tells the client not to print any of the normal information to stderr - * @throws IOException if communication with the server fails - * @throws UnknownHostException if the host could not be found - */ - public MaryHttpClient(Address serverAddress, boolean profile, boolean quiet) throws IOException - { - super(serverAddress, profile, quiet); - } - - - - - /////////////////////////////////////////////////////////////////////// - //////////////////////// Information requests ///////////////////////// - /////////////////////////////////////////////////////////////////////// - - @Override - protected void fillAudioFileFormatAndOutTypes() throws IOException - { - String audioFormatInfo = serverInfoRequest("audioformats", null); - data.audioOutTypes = new Vector(Arrays.asList(StringUtils.toStringArray(audioFormatInfo))); - data.audioFileFormatTypes = new Vector(); - for (String af : data.audioOutTypes) { - if (af.endsWith("_FILE")) { - String typeName = af.substring(0, af.indexOf("_")); - try { - AudioFileFormat.Type type = MaryClient.getAudioFileFormatType(typeName); - data.audioFileFormatTypes.add(typeName+" "+type.getExtension()); - } catch (Exception e) {} - } - } - } - - @Override - protected void fillServerVersion() throws IOException - { - data.toServerVersionInfo(serverInfoRequest("version", null)); - } - - - - - @Override - protected void fillDataTypes() throws IOException - { - data.toDataTypes(serverInfoRequest("datatypes", null)); - } - - - - protected void fillVoices() throws IOException - { - data.toVoices(serverInfoRequest("voices", null)); - } - - @Override - protected void fillLocales() throws IOException { - data.toLocales(serverInfoRequest("locales", null)); - } - - @Override - protected void fillVoiceExampleTexts(String voicename) throws IOException - { - Map queryItems = new HashMap(); - queryItems.put("voice", voicename); - String info = serverInfoRequest("exampletext", queryItems); - - if (info.length() == 0) - throw new IOException("Could not get example text from Mary server"); - - StringTokenizer st = new StringTokenizer(info,"\n"); - Vector sentences = new Vector(); - while (st.hasMoreTokens()) { - sentences.add(st.nextToken()); - } - data.voiceExampleTextsLimitedDomain.put(voicename, sentences); - } - - @Override - protected void fillServerExampleText(String dataType, String locale) throws IOException - { - Map queryItems = new HashMap(); - queryItems.put("datatype", dataType); - queryItems.put("locale", locale); - String info = serverInfoRequest("exampletext", queryItems); - - if (info.length() == 0) - throw new IOException("Could not get example text from Mary server"); - - data.serverExampleTexts.put(dataType+" "+locale, info.replaceAll("\n", System.getProperty("line.separator"))); - } - - /** - * Request the available audio effects for a voice from the server - * @param voicename the voice - * @return A string of available audio effects and default parameters, i.e. "FIRFilter,Robot(amount=50)" - * @throws IOException - * @throws UnknownHostException - */ - @Override - protected String getDefaultAudioEffects() throws IOException - { - return serverInfoRequest("audioeffects", null); - } - - @Override - public String requestDefaultEffectParameters(String effectName) throws IOException - { - Map queryItems = new HashMap(); - queryItems.put("effect", effectName); - - String info = serverInfoRequest("audioeffect-default-param", queryItems); - - if (info==null || info.length() == 0) - return ""; - - return info.replaceAll("\n", System.getProperty("line.separator")); - } - - @Override - public String requestFullEffect(String effectName, String currentEffectParameters) throws IOException - { - Map queryItems = new HashMap(); - queryItems.put("effect", effectName); - queryItems.put("params", currentEffectParameters); - - String info = serverInfoRequest("audioeffect-full", queryItems); - - if (info.length() == 0) - return ""; - - return info.replaceAll("\n", System.getProperty("line.separator")); - } - - @Override - protected void fillEffectHelpText(String effectName) throws IOException - { - Map queryItems = new HashMap(); - queryItems.put("effect", effectName); - - String info = serverInfoRequest("audioeffect-help", queryItems); - data.audioEffectHelpTextsMap.put(effectName, info.replaceAll("\n", System.getProperty("line.separator"))); - } - - @Override - public boolean isHMMEffect(String effectName) throws IOException - { - Map queryItems = new HashMap(); - queryItems.put("effect", effectName); - - String info = serverInfoRequest("audioeffect-is-hmm-effect", queryItems); - - if (info.length() == 0) - return false; - - boolean bRet = false; - info = info.toLowerCase(); - if (info.indexOf("yes")>-1) - bRet = true; - - return bRet; - } - - public String getFeatures(String locale) throws IOException - { - return serverInfoRequest("features?locale="+locale, null); - } - - public String getDiscreteFeatures(String locale) throws IOException - { - return serverInfoRequest("features-discrete?locale="+locale, null); - } - - public String getFeaturesForVoice(String voice) throws IOException - { - return serverInfoRequest("features?voice="+voice, null); - } - - private String serverInfoRequest(String request, MapqueryItems) - throws IOException - { - StringBuilder url = new StringBuilder(); - url.append(data.hostAddress.getHttpAddress()).append("/").append(request); - if (queryItems != null) { - url.append("?"); - boolean first = true; - for (String key : queryItems.keySet()) { - if (first) first = false; - else url.append("&"); - url.append(key).append("="); - url.append(URLEncoder.encode(queryItems.get(key), "UTF-8")); - } - } - return serverInfoRequest(new URL(url.toString())); - - } - - private String serverInfoRequest(URL url) - throws IOException - { - HttpURLConnection http = (HttpURLConnection)url.openConnection(); - http.setRequestMethod("GET"); - http.connect(); - +package marytts.client.http; + +// General Java Classes +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.Timer; +import java.util.TimerTask; +import java.util.Vector; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.AudioFormat.Encoding; + +import marytts.client.MaryClient; +import marytts.client.MaryGUIClient; +import marytts.util.http.Address; +import marytts.util.io.FileUtils; +import marytts.util.string.StringUtils; + +/** + * An HTTP client implementing the MARY protocol. + * It can be used as a command line client or from within java code. + * @author Marc Schröder, oytun.turk + * @see MaryGUIClient A GUI interface to this client + * @see marytts.server.MaryServer Description of the MARY protocol + */ + +public class MaryHttpClient extends MaryClient +{ + + /** + * The simplest way to create a mary client. It will connect to the + * MARY server running at DFKI. Only use this for testing purposes! + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public MaryHttpClient() throws IOException + { + super(); + } + + public MaryHttpClient(boolean quiet) throws IOException + { + super(quiet); + } + + /** + * The typical way to create a mary client. It will connect to the + * MARY client running at the given host and port. + * This constructor reads two system properties: + *
    + *
  • mary.client.profile (=true/false) - + * determines whether profiling (timing) information is calculated;
  • + *
  • mary.client.quiet (=true/false) - + * tells the client not to print any of the normal information to stderr.
  • + *
+ * @param host the host where to contact a MARY server + * @param port the socket port where to contact a MARY server + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public MaryHttpClient(Address serverAddress) throws IOException + { + super(serverAddress); + } + + /** + * An alternative way to create a mary client, which works with applets. + * It will connect to the MARY client running at the given host and port. + * Note that in applets, the host must be the same as the one from which + * the applet was loaded; otherwise, a security exception is thrown. + * @param host the host where to contact a MARY server + * @param port the socket port where to contact a MARY server + * @param profile determines whether profiling (timing) information is calculated + * @param quiet tells the client not to print any of the normal information to stderr + * @throws IOException if communication with the server fails + * @throws UnknownHostException if the host could not be found + */ + public MaryHttpClient(Address serverAddress, boolean profile, boolean quiet) throws IOException + { + super(serverAddress, profile, quiet); + } + + + + + /////////////////////////////////////////////////////////////////////// + //////////////////////// Information requests ///////////////////////// + /////////////////////////////////////////////////////////////////////// + + @Override + protected void fillAudioFileFormatAndOutTypes() throws IOException + { + String audioFormatInfo = serverInfoRequest("audioformats", null); + data.audioOutTypes = new Vector(Arrays.asList(StringUtils.toStringArray(audioFormatInfo))); + data.audioFileFormatTypes = new Vector(); + for (String af : data.audioOutTypes) { + if (af.endsWith("_FILE")) { + String typeName = af.substring(0, af.indexOf("_")); + try { + AudioFileFormat.Type type = MaryClient.getAudioFileFormatType(typeName); + data.audioFileFormatTypes.add(typeName+" "+type.getExtension()); + } catch (Exception e) {} + } + } + } + + @Override + protected void fillServerVersion() throws IOException + { + data.toServerVersionInfo(serverInfoRequest("version", null)); + } + + + + + @Override + protected void fillDataTypes() throws IOException + { + data.toDataTypes(serverInfoRequest("datatypes", null)); + } + + + + protected void fillVoices() throws IOException + { + data.toVoices(serverInfoRequest("voices", null)); + } + + @Override + protected void fillLocales() throws IOException { + data.toLocales(serverInfoRequest("locales", null)); + } + + @Override + protected void fillVoiceExampleTexts(String voicename) throws IOException + { + Map queryItems = new HashMap(); + queryItems.put("voice", voicename); + String info = serverInfoRequest("exampletext", queryItems); + + if (info.length() == 0) + throw new IOException("Could not get example text from Mary server"); + + StringTokenizer st = new StringTokenizer(info,"\n"); + Vector sentences = new Vector(); + while (st.hasMoreTokens()) { + sentences.add(st.nextToken()); + } + data.voiceExampleTextsLimitedDomain.put(voicename, sentences); + } + + @Override + protected void fillServerExampleText(String dataType, String locale) throws IOException + { + Map queryItems = new HashMap(); + queryItems.put("datatype", dataType); + queryItems.put("locale", locale); + String info = serverInfoRequest("exampletext", queryItems); + + if (info.length() == 0) + throw new IOException("Could not get example text from Mary server"); + + data.serverExampleTexts.put(dataType+" "+locale, info.replaceAll("\n", System.getProperty("line.separator"))); + } + + /** + * Request the available audio effects for a voice from the server + * @param voicename the voice + * @return A string of available audio effects and default parameters, i.e. "FIRFilter,Robot(amount=50)" + * @throws IOException + * @throws UnknownHostException + */ + @Override + protected String getDefaultAudioEffects() throws IOException + { + return serverInfoRequest("audioeffects", null); + } + + @Override + public String requestDefaultEffectParameters(String effectName) throws IOException + { + Map queryItems = new HashMap(); + queryItems.put("effect", effectName); + + String info = serverInfoRequest("audioeffect-default-param", queryItems); + + if (info==null || info.length() == 0) + return ""; + + return info.replaceAll("\n", System.getProperty("line.separator")); + } + + @Override + public String requestFullEffect(String effectName, String currentEffectParameters) throws IOException + { + Map queryItems = new HashMap(); + queryItems.put("effect", effectName); + queryItems.put("params", currentEffectParameters); + + String info = serverInfoRequest("audioeffect-full", queryItems); + + if (info.length() == 0) + return ""; + + return info.replaceAll("\n", System.getProperty("line.separator")); + } + + @Override + protected void fillEffectHelpText(String effectName) throws IOException + { + Map queryItems = new HashMap(); + queryItems.put("effect", effectName); + + String info = serverInfoRequest("audioeffect-help", queryItems); + data.audioEffectHelpTextsMap.put(effectName, info.replaceAll("\n", System.getProperty("line.separator"))); + } + + @Override + public boolean isHMMEffect(String effectName) throws IOException + { + Map queryItems = new HashMap(); + queryItems.put("effect", effectName); + + String info = serverInfoRequest("audioeffect-is-hmm-effect", queryItems); + + if (info.length() == 0) + return false; + + boolean bRet = false; + info = info.toLowerCase(); + if (info.indexOf("yes")>-1) + bRet = true; + + return bRet; + } + + public String getFeatures(String locale) throws IOException + { + return serverInfoRequest("features?locale="+locale, null); + } + + public String getDiscreteFeatures(String locale) throws IOException + { + return serverInfoRequest("features-discrete?locale="+locale, null); + } + + public String getFeaturesForVoice(String voice) throws IOException + { + return serverInfoRequest("features?voice="+voice, null); + } + + private String serverInfoRequest(String request, MapqueryItems) + throws IOException + { + StringBuilder url = new StringBuilder(); + url.append(data.hostAddress.getHttpAddress()).append("/").append(request); + if (queryItems != null) { + url.append("?"); + boolean first = true; + for (String key : queryItems.keySet()) { + if (first) first = false; + else url.append("&"); + url.append(key).append("="); + url.append(URLEncoder.encode(queryItems.get(key), "UTF-8")); + } + } + return serverInfoRequest(new URL(url.toString())); + + } + + private String serverInfoRequest(URL url) + throws IOException + { + HttpURLConnection http = (HttpURLConnection)url.openConnection(); + http.setRequestMethod("GET"); + http.connect(); + if(http.getResponseCode() != HttpURLConnection.HTTP_OK) { - String errorData = ""; - try { - errorData = FileUtils.getStreamAsString(http.getErrorStream(), "UTF-8"); + String errorData = ""; + try { + errorData = FileUtils.getStreamAsString(http.getErrorStream(), "UTF-8"); } catch (Exception e) {} throw new IOException(http.getResponseCode() + ":" + http.getResponseMessage() +"\n"+errorData); } return FileUtils.getStreamAsString(http.getInputStream(), "UTF-8"); -/* The following is example code if we were to use HttpClient: - * HttpClient httpclient = new DefaultHttpClient(); - - HttpGet httpget = new HttpGet("http://www.google.com/"); - - System.out.println("executing request " + httpget.getURI()); - - // Create a response handler - ResponseHandler responseHandler = new BasicResponseHandler(); - String responseBody = httpclient.execute(httpget, responseHandler); - System.out.println(responseBody); -*/ - } - -/* private String getFromServer(String key) throws IOException - { - return getFromServer(key, null); - } - - //This handles each request one by one - private String getFromServer(String key, String params) throws IOException - { - if (data.keyValuePairs==null) - data.keyValuePairs = new HashMap(); - - Map singleKeyValuePair = new HashMap(); - - if (params==null || params.length()<1) - singleKeyValuePair.put(key, "?"); - else - singleKeyValuePair.put(key, "? " + params); - - singleKeyValuePair = httpRequester.request(data.hostAddress, singleKeyValuePair); - - data.keyValuePairs.put(key, singleKeyValuePair.get(key)); - - return data.keyValuePairs.get(key); - } - - */ - - - - - - - - - - - - - - - - - - /////////////////////////////////////////////////////////////////////// - //////////////////////// Actual synthesis requests //////////////////// - /////////////////////////////////////////////////////////////////////// - - - private InputStream requestInputStream(String input, String inputType, String outputType, String locale, String audioType, - String defaultVoiceName, String defaultStyle, Map effects, //String defaultEffects, - boolean streamingAudio, String outputTypeParams) throws IOException - { - - StringBuilder params = new StringBuilder(); - params.append("INPUT_TEXT=").append(URLEncoder.encode(input, "UTF-8")); - params.append("&INPUT_TYPE=").append(URLEncoder.encode(inputType, "UTF-8")); - params.append("&OUTPUT_TYPE=").append(URLEncoder.encode(outputType, "UTF-8")); - if (locale != null) { - params.append("&LOCALE=").append(URLEncoder.encode(locale, "UTF-8")); - } - if (audioType != null) { - params.append("&AUDIO=").append(URLEncoder.encode((streamingAudio && data.serverCanStream) ? audioType+"_STREAM" : audioType + "_FILE", "UTF-8")); - } - if (outputTypeParams != null) { - params.append("&OUTPUT_TYPE_PARAMS=").append(URLEncoder.encode(outputTypeParams, "UTF-8")); - } - - if (defaultVoiceName != null) { - params.append("&VOICE=").append(URLEncoder.encode(defaultVoiceName, "UTF-8")); - } - - if (defaultStyle != null) { - params.append("&STYLE=").append(URLEncoder.encode(defaultStyle, "UTF-8")); - } - - if (effects != null) { - for (String key : effects.keySet()) { - params.append("&").append(key).append("=").append(URLEncoder.encode(effects.get(key), "UTF-8")); - } - } - - //to make HTTP Post request with HttpURLConnection - URL url = new URL(data.hostAddress.getHttpAddress()+"/process"); - HttpURLConnection conn = (HttpURLConnection)url.openConnection(); - - conn.setRequestMethod("POST"); - conn.setAllowUserInteraction(false); // no user interact [like pop up] - conn.setDoOutput(true); // want to send - conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); - OutputStream ost = conn.getOutputStream(); - PrintWriter pw = new PrintWriter(ost); - pw.print(params.toString()); // here we "send" our body! - pw.flush(); - pw.close(); - - //and InputStream from here will be body - try { - return conn.getInputStream(); - } catch (IOException e) { - String error; - try { - error = FileUtils.getStreamAsString(conn.getErrorStream(), "UTF-8"); - } catch (IOException errE) { - // ok cannot get error message, just re-throw original e - throw new IOException("No detailed error message available", e); - } - throw new IOException("Error message from server:\n"+error, e); - } - - } - - private Map effectsString2EffectsMap(String effectsString) - { - if (effectsString == null) return null; - Map effectsMap = new HashMap(); - - StringTokenizer st = new StringTokenizer(effectsString, ","); - while (st.hasMoreTokens()) { - String oneEffect = st.nextToken().trim(); - String name; - String params; - int iBracket = oneEffect.indexOf('('); - if (iBracket > -1) { - name = oneEffect.substring(0, iBracket); - params = oneEffect.substring(iBracket+1, oneEffect.indexOf(')', iBracket+1)); - } else { // no parameters - name = oneEffect; - params = ""; - } - effectsMap.put("effect_"+name+"_selected", "on"); - effectsMap.put("effect_"+name+"_parameters", params); - } - return effectsMap; - } - - @Override - protected void _process(String input, String inputType, String outputType, String locale, String audioType, - String defaultVoiceName, String defaultStyle, String defaultEffects, - Object output, long timeout, boolean streamingAudio, String outputTypeParams, AudioPlayerListener playerListener) - throws IOException - { - boolean isMaryAudioPlayer = false; - if (output instanceof marytts.util.data.audio.AudioPlayer) { - isMaryAudioPlayer = true; - } else if (output instanceof OutputStream) { - } else { - throw new IllegalArgumentException("Expected OutputStream or AudioPlayer, got " + output.getClass().getName()); - } - final long startTime = System.currentTimeMillis(); - - final InputStream fromServerStream = requestInputStream(input, inputType, outputType, locale, audioType, - defaultVoiceName, defaultStyle, effectsString2EffectsMap(defaultEffects), - streamingAudio, outputTypeParams); - - // If timeout is > 0, create a timer. It will close the input stream, - // thus causing an IOException in the reading code. - final Timer timer; - if (timeout <= 0) { - timer = null; - } else { - timer = new Timer(); - TimerTask timerTask = new TimerTask() { - public void run() { - System.err.println("Timer closes connection"); - /* - try { - maryDataSocket.close(); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - */ - } - }; - timer.schedule(timerTask, timeout); - } - - if (isMaryAudioPlayer) - { - final marytts.util.data.audio.AudioPlayer player = (marytts.util.data.audio.AudioPlayer) output; - final AudioPlayerListener listener = playerListener; - Thread t = new Thread() { - public void run() - { - try { - InputStream in = fromServerStream; - if (doProfile) - System.err.println("After "+(System.currentTimeMillis()-startTime)+" ms: Trying to read data from server"); - in = new BufferedInputStream(in); - in.mark(1000); - AudioInputStream fromServerAudio = AudioSystem.getAudioInputStream(in); - - if (fromServerAudio.getFrameLength() == 0) { // weird bug under Java 1.4 - //in.reset(); - fromServerAudio = new AudioInputStream(in, fromServerAudio.getFormat(), AudioSystem.NOT_SPECIFIED); - } - //System.out.println("Audio framelength: "+fromServerAudio.getFrameLength()); - //System.out.println("Audio frame size: "+fromServerAudio.getFormat().getFrameSize()); - //System.out.println("Audio format: "+fromServerAudio.getFormat()); - if (doProfile) - System.err.println("After "+(System.currentTimeMillis()-startTime)+" ms: Audio available: "+in.available()); - AudioFormat audioFormat = fromServerAudio.getFormat(); - if (!audioFormat.getEncoding().equals(Encoding.PCM_SIGNED)) { // need conversion, e.g. for mp3 - audioFormat = new AudioFormat(fromServerAudio.getFormat().getSampleRate(), 16, 1, true, false); - fromServerAudio = AudioSystem.getAudioInputStream(audioFormat, fromServerAudio); - } - player.setAudio(fromServerAudio); - player.run(); // not start(), i.e. execute in this thread - - if (timer != null) - timer.cancel(); - - if (listener != null) - listener.playerFinished(); - - //toServerInfo.close(); - //fromServerInfo.close(); - //maryInfoSocket.close(); - //toServerData.close(); - //maryDataSocket.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - //try { - // warningReader.join(); - //} catch (InterruptedException ie) {} - //if (warningReader.getWarnings().length() > 0) { // there are warnings - // String warnings = warningReader.getWarnings(); - // System.err.println(warnings); - // if (listener != null) listener.playerException(new IOException(warnings)); - //} - - if (doProfile) - { - long endTime = System.currentTimeMillis(); - long processingTime = endTime - startTime; - System.err.println("Processed request in " + processingTime + " ms."); - } - } - }; - - if (streamingAudio) - t.start(); - else - t.run(); // execute code in the current thread - } - else // output is an OutputStream - { - OutputStream os = (OutputStream) output; - InputStream bis = new BufferedInputStream(fromServerStream); - byte[] bbuf = new byte[1024]; - int nr; - while ((nr = bis.read(bbuf, 0, bbuf.length)) != -1) - { - //System.err.println("Read " + nr + " bytes from server."); - os.write(bbuf, 0, nr); - } - os.flush(); - - if (timeout > 0) - timer.cancel(); - - //toServerInfo.close(); - //fromServerInfo.close(); - //maryInfoSocket.close(); - //toServerData.close(); - //maryDataSocket.close(); - - //try { - // warningReader.join(); - //} catch (InterruptedException ie) {} - //if (warningReader.getWarnings().length() > 0) // there are warnings - // throw new IOException(warningReader.getWarnings()); - - if (doProfile) - { - long endTime = System.currentTimeMillis(); - long processingTime = endTime - startTime; - System.err.println("Processed request in " + processingTime + " ms."); - } - } - } - - - - -} +/* The following is example code if we were to use HttpClient: + * HttpClient httpclient = new DefaultHttpClient(); + + HttpGet httpget = new HttpGet("http://www.google.com/"); + + System.out.println("executing request " + httpget.getURI()); + + // Create a response handler + ResponseHandler responseHandler = new BasicResponseHandler(); + String responseBody = httpclient.execute(httpget, responseHandler); + System.out.println(responseBody); +*/ + } + +/* private String getFromServer(String key) throws IOException + { + return getFromServer(key, null); + } + + //This handles each request one by one + private String getFromServer(String key, String params) throws IOException + { + if (data.keyValuePairs==null) + data.keyValuePairs = new HashMap(); + + Map singleKeyValuePair = new HashMap(); + + if (params==null || params.length()<1) + singleKeyValuePair.put(key, "?"); + else + singleKeyValuePair.put(key, "? " + params); + + singleKeyValuePair = httpRequester.request(data.hostAddress, singleKeyValuePair); + + data.keyValuePairs.put(key, singleKeyValuePair.get(key)); + + return data.keyValuePairs.get(key); + } + + */ + + + + + + + + + + + + + + + + + + /////////////////////////////////////////////////////////////////////// + //////////////////////// Actual synthesis requests //////////////////// + /////////////////////////////////////////////////////////////////////// + + + private InputStream requestInputStream(String input, String inputType, String outputType, String locale, String audioType, + String defaultVoiceName, String defaultStyle, Map effects, //String defaultEffects, + boolean streamingAudio, String outputTypeParams) throws IOException + { + + StringBuilder params = new StringBuilder(); + params.append("INPUT_TEXT=").append(URLEncoder.encode(input, "UTF-8")); + params.append("&INPUT_TYPE=").append(URLEncoder.encode(inputType, "UTF-8")); + params.append("&OUTPUT_TYPE=").append(URLEncoder.encode(outputType, "UTF-8")); + if (locale != null) { + params.append("&LOCALE=").append(URLEncoder.encode(locale, "UTF-8")); + } + if (audioType != null) { + params.append("&AUDIO=").append(URLEncoder.encode((streamingAudio && data.serverCanStream) ? audioType+"_STREAM" : audioType + "_FILE", "UTF-8")); + } + if (outputTypeParams != null) { + params.append("&OUTPUT_TYPE_PARAMS=").append(URLEncoder.encode(outputTypeParams, "UTF-8")); + } + + if (defaultVoiceName != null) { + params.append("&VOICE=").append(URLEncoder.encode(defaultVoiceName, "UTF-8")); + } + + if (defaultStyle != null) { + params.append("&STYLE=").append(URLEncoder.encode(defaultStyle, "UTF-8")); + } + + if (effects != null) { + for (String key : effects.keySet()) { + params.append("&").append(key).append("=").append(URLEncoder.encode(effects.get(key), "UTF-8")); + } + } + + //to make HTTP Post request with HttpURLConnection + URL url = new URL(data.hostAddress.getHttpAddress()+"/process"); + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + + conn.setRequestMethod("POST"); + conn.setAllowUserInteraction(false); // no user interact [like pop up] + conn.setDoOutput(true); // want to send + conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); + OutputStream ost = conn.getOutputStream(); + PrintWriter pw = new PrintWriter(ost); + pw.print(params.toString()); // here we "send" our body! + pw.flush(); + pw.close(); + + //and InputStream from here will be body + try { + return conn.getInputStream(); + } catch (IOException e) { + String error; + try { + error = FileUtils.getStreamAsString(conn.getErrorStream(), "UTF-8"); + } catch (IOException errE) { + // ok cannot get error message, just re-throw original e + throw new IOException("No detailed error message available", e); + } + throw new IOException("Error message from server:\n"+error, e); + } + + } + + private Map effectsString2EffectsMap(String effectsString) + { + if (effectsString == null) return null; + Map effectsMap = new HashMap(); + + StringTokenizer st = new StringTokenizer(effectsString, ","); + while (st.hasMoreTokens()) { + String oneEffect = st.nextToken().trim(); + String name; + String params; + int iBracket = oneEffect.indexOf('('); + if (iBracket > -1) { + name = oneEffect.substring(0, iBracket); + params = oneEffect.substring(iBracket+1, oneEffect.indexOf(')', iBracket+1)); + } else { // no parameters + name = oneEffect; + params = ""; + } + effectsMap.put("effect_"+name+"_selected", "on"); + effectsMap.put("effect_"+name+"_parameters", params); + } + return effectsMap; + } + + @Override + protected void _process(String input, String inputType, String outputType, String locale, String audioType, + String defaultVoiceName, String defaultStyle, String defaultEffects, + Object output, long timeout, boolean streamingAudio, String outputTypeParams, AudioPlayerListener playerListener) + throws IOException + { + boolean isMaryAudioPlayer = false; + if (output instanceof marytts.util.data.audio.AudioPlayer) { + isMaryAudioPlayer = true; + } else if (output instanceof OutputStream) { + } else { + throw new IllegalArgumentException("Expected OutputStream or AudioPlayer, got " + output.getClass().getName()); + } + final long startTime = System.currentTimeMillis(); + + final InputStream fromServerStream = requestInputStream(input, inputType, outputType, locale, audioType, + defaultVoiceName, defaultStyle, effectsString2EffectsMap(defaultEffects), + streamingAudio, outputTypeParams); + + // If timeout is > 0, create a timer. It will close the input stream, + // thus causing an IOException in the reading code. + final Timer timer; + if (timeout <= 0) { + timer = null; + } else { + timer = new Timer(); + TimerTask timerTask = new TimerTask() { + public void run() { + System.err.println("Timer closes connection"); + /* + try { + maryDataSocket.close(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + */ + } + }; + timer.schedule(timerTask, timeout); + } + + if (isMaryAudioPlayer) + { + final marytts.util.data.audio.AudioPlayer player = (marytts.util.data.audio.AudioPlayer) output; + final AudioPlayerListener listener = playerListener; + Thread t = new Thread() { + public void run() + { + try { + InputStream in = fromServerStream; + if (doProfile) + System.err.println("After "+(System.currentTimeMillis()-startTime)+" ms: Trying to read data from server"); + in = new BufferedInputStream(in); + in.mark(1000); + AudioInputStream fromServerAudio = AudioSystem.getAudioInputStream(in); + + if (fromServerAudio.getFrameLength() == 0) { // weird bug under Java 1.4 + //in.reset(); + fromServerAudio = new AudioInputStream(in, fromServerAudio.getFormat(), AudioSystem.NOT_SPECIFIED); + } + //System.out.println("Audio framelength: "+fromServerAudio.getFrameLength()); + //System.out.println("Audio frame size: "+fromServerAudio.getFormat().getFrameSize()); + //System.out.println("Audio format: "+fromServerAudio.getFormat()); + if (doProfile) + System.err.println("After "+(System.currentTimeMillis()-startTime)+" ms: Audio available: "+in.available()); + AudioFormat audioFormat = fromServerAudio.getFormat(); + if (!audioFormat.getEncoding().equals(Encoding.PCM_SIGNED)) { // need conversion, e.g. for mp3 + audioFormat = new AudioFormat(fromServerAudio.getFormat().getSampleRate(), 16, 1, true, false); + fromServerAudio = AudioSystem.getAudioInputStream(audioFormat, fromServerAudio); + } + player.setAudio(fromServerAudio); + player.run(); // not start(), i.e. execute in this thread + + if (timer != null) + timer.cancel(); + + if (listener != null) + listener.playerFinished(); + + //toServerInfo.close(); + //fromServerInfo.close(); + //maryInfoSocket.close(); + //toServerData.close(); + //maryDataSocket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + //try { + // warningReader.join(); + //} catch (InterruptedException ie) {} + //if (warningReader.getWarnings().length() > 0) { // there are warnings + // String warnings = warningReader.getWarnings(); + // System.err.println(warnings); + // if (listener != null) listener.playerException(new IOException(warnings)); + //} + + if (doProfile) + { + long endTime = System.currentTimeMillis(); + long processingTime = endTime - startTime; + System.err.println("Processed request in " + processingTime + " ms."); + } + } + }; + + if (streamingAudio) + t.start(); + else + t.run(); // execute code in the current thread + } + else // output is an OutputStream + { + OutputStream os = (OutputStream) output; + InputStream bis = new BufferedInputStream(fromServerStream); + byte[] bbuf = new byte[1024]; + int nr; + while ((nr = bis.read(bbuf, 0, bbuf.length)) != -1) + { + //System.err.println("Read " + nr + " bytes from server."); + os.write(bbuf, 0, nr); + } + os.flush(); + + if (timeout > 0) + timer.cancel(); + + //toServerInfo.close(); + //fromServerInfo.close(); + //maryInfoSocket.close(); + //toServerData.close(); + //maryDataSocket.close(); + + //try { + // warningReader.join(); + //} catch (InterruptedException ie) {} + //if (warningReader.getWarnings().length() > 0) // there are warnings + // throw new IOException(warningReader.getWarnings()); + + if (doProfile) + { + long endTime = System.currentTimeMillis(); + long processingTime = endTime - startTime; + System.err.println("Processed request in " + processingTime + " ms."); + } + } + } + + + + +} diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/AsynchronousThreadedMaryClient.java b/marytts-client/src/main/java/marytts/tools/emospeak/AsynchronousThreadedMaryClient.java index 7a4babf0..778632a4 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/AsynchronousThreadedMaryClient.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/AsynchronousThreadedMaryClient.java @@ -33,61 +33,60 @@ import javax.sound.sampled.UnsupportedAudioFileException; import marytts.client.MaryClient; import marytts.util.http.Address; - /** - * A MaryClient that runs in a thread of its own. Requests for synthesis - * are scheduled through scheduleRequest(), which is not - * synchronized. Only the last unprocessed request is remembered. - * - * @author Marc Schröder + * A MaryClient that runs in a thread of its own. Requests for synthesis are scheduled through scheduleRequest(), + * which is not synchronized. Only the last unprocessed request is remembered. + * + * @author Marc Schröder */ public class AsynchronousThreadedMaryClient extends Thread { - private int r; - private AudioFileReceiver emoSpeak; - private marytts.client.MaryClient processor; - private boolean inputAvailable = false; - private String latestRequest = null; - private MaryClient.Voice latestRequestVoice = null; - private AudioInputStream latestAudio = null; - private boolean exitRequested = false; - - /** Creates new AsynchronousThreadedMaryClient */ - public AsynchronousThreadedMaryClient(AudioFileReceiver emoSpeak) - throws IOException, UnknownHostException { - this.emoSpeak = emoSpeak; - processor = MaryClient.getMaryClient(); - } + private int r; + private AudioFileReceiver emoSpeak; + private marytts.client.MaryClient processor; + private boolean inputAvailable = false; + private String latestRequest = null; + private MaryClient.Voice latestRequestVoice = null; + private AudioInputStream latestAudio = null; + private boolean exitRequested = false; - /** Constructor to be used by applets */ - public AsynchronousThreadedMaryClient(AudioFileReceiver emoSpeak, - String serverHost, int serverPort, boolean printProfilingInfo, boolean beQuiet) - throws IOException, UnknownHostException { - this.emoSpeak = emoSpeak; - processor = MaryClient.getMaryClient(new Address(serverHost, serverPort), printProfilingInfo, beQuiet); - } + /** Creates new AsynchronousThreadedMaryClient */ + public AsynchronousThreadedMaryClient(AudioFileReceiver emoSpeak) throws IOException, UnknownHostException { + this.emoSpeak = emoSpeak; + processor = MaryClient.getMaryClient(); + } - /** - * Schedule the latest request. Any previous, unprocessed requests - * are deleted. - * @param prosodyxmlString the maryxml data to be synthesised. - * @param voice the synthesis voice to use - * @param requestNumber request number - */ - public synchronized void scheduleRequest(String prosodyxmlString, MaryClient.Voice voice, int requestNumber) { - latestRequest = prosodyxmlString; - latestRequestVoice = voice; - inputAvailable = true; - this.r = requestNumber; - notifyAll(); - } - - public synchronized void requestExit() { - exitRequested = true; - notifyAll(); - } + /** Constructor to be used by applets */ + public AsynchronousThreadedMaryClient(AudioFileReceiver emoSpeak, String serverHost, int serverPort, + boolean printProfilingInfo, boolean beQuiet) throws IOException, UnknownHostException { + this.emoSpeak = emoSpeak; + processor = MaryClient.getMaryClient(new Address(serverHost, serverPort), printProfilingInfo, beQuiet); + } - // Call the mary client - private void processInput() + /** + * Schedule the latest request. Any previous, unprocessed requests are deleted. + * + * @param prosodyxmlString + * the maryxml data to be synthesised. + * @param voice + * the synthesis voice to use + * @param requestNumber + * request number + */ + public synchronized void scheduleRequest(String prosodyxmlString, MaryClient.Voice voice, int requestNumber) { + latestRequest = prosodyxmlString; + latestRequestVoice = voice; + inputAvailable = true; + this.r = requestNumber; + notifyAll(); + } + + public synchronized void requestExit() { + exitRequested = true; + notifyAll(); + } + + // Call the mary client + private void processInput() throws IOException, UnknownHostException, UnsupportedAudioFileException { java.io.ByteArrayOutputStream os = new ByteArrayOutputStream(); assert latestRequestVoice != null; @@ -101,59 +100,56 @@ public class AsynchronousThreadedMaryClient extends Thread { byte[] bytes = os.toByteArray(); latestAudio = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes)); } - - public String getHost() - { - return processor.getHost(); - } - - public int getPort() - { - return processor.getPort(); - } - public Vector getServerVoices() throws IOException - { - return processor.getGeneralDomainVoices(); - } - - public Vector getServerVoices(Locale locale) throws IOException - { - return processor.getGeneralDomainVoices(locale); - } + public String getHost() { + return processor.getHost(); + } - private synchronized void doWait() { - try { - wait(); - } catch (InterruptedException e) {} - } - - public void run() { - while (!exitRequested) { - if (inputAvailable) { - // heuristic sleep value, waiting for more reasonable new mouse position: - try { - sleep(200); - } catch (InterruptedException e) {} - inputAvailable = false; - int r1 = r; - long t0 = System.currentTimeMillis(); - try { - processInput(); - long t = System.currentTimeMillis() - t0; - System.err.println("MaryClient has processed request no." + r1 + " in " + t + " ms."); - emoSpeak.setNextAudio(latestAudio); - } catch (Exception e) { - System.err.println("Problem creating synthesis audio:"); - e.printStackTrace(); - emoSpeak.setNextAudio(null); - } - } else { - doWait(); - System.err.println("MaryClient waking up from wait."); - } - } - System.err.println("MaryClient exiting."); - } + public int getPort() { + return processor.getPort(); + } + + public Vector getServerVoices() throws IOException { + return processor.getGeneralDomainVoices(); + } + + public Vector getServerVoices(Locale locale) throws IOException { + return processor.getGeneralDomainVoices(locale); + } + + private synchronized void doWait() { + try { + wait(); + } catch (InterruptedException e) { + } + } + + public void run() { + while (!exitRequested) { + if (inputAvailable) { + // heuristic sleep value, waiting for more reasonable new mouse position: + try { + sleep(200); + } catch (InterruptedException e) { + } + inputAvailable = false; + int r1 = r; + long t0 = System.currentTimeMillis(); + try { + processInput(); + long t = System.currentTimeMillis() - t0; + System.err.println("MaryClient has processed request no." + r1 + " in " + t + " ms."); + emoSpeak.setNextAudio(latestAudio); + } catch (Exception e) { + System.err.println("Problem creating synthesis audio:"); + e.printStackTrace(); + emoSpeak.setNextAudio(null); + } + } else { + doWait(); + System.err.println("MaryClient waking up from wait."); + } + } + System.err.println("MaryClient exiting."); + } } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/AudioFileReceiver.java b/marytts-client/src/main/java/marytts/tools/emospeak/AudioFileReceiver.java index 7208369b..869be997 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/AudioFileReceiver.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/AudioFileReceiver.java @@ -20,12 +20,11 @@ package marytts.tools.emospeak; /** - * - * @author schroed + * + * @author schroed */ public interface AudioFileReceiver { - - public void setNextAudio(javax.sound.sampled.AudioInputStream audioInputStream); - -} + public void setNextAudio(javax.sound.sampled.AudioInputStream audioInputStream); + +} diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeak.java b/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeak.java index 383b4fa6..a48f824a 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeak.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeak.java @@ -23,57 +23,56 @@ import java.io.IOException; import java.net.UnknownHostException; /** - * - * @author Marc Schröder + * + * @author Marc Schröder */ -public class EmoSpeak extends javax.swing.JFrame -{ - /** Creates new form EmoSpeak */ - public EmoSpeak() throws Exception { - super("OpenMary EmoSpeak"); - initComponents(); - emoSpeakPanel1.initialiseMenu(); - } - - /** This method is called from within the constructor to - * initialize the form. - */ - private void initComponents() throws IOException, UnknownHostException { - emoSpeakPanel1 = new EmoSpeakPanel(true, System.getProperty("server.host", "cling.dfki.uni-sb.de"), Integer.getInteger("server.port", 59125).intValue()); +public class EmoSpeak extends javax.swing.JFrame { + /** Creates new form EmoSpeak */ + public EmoSpeak() throws Exception { + super("OpenMary EmoSpeak"); + initComponents(); + emoSpeakPanel1.initialiseMenu(); + } - getContentPane().setLayout(new java.awt.FlowLayout()); + /** + * This method is called from within the constructor to initialize the form. + */ + private void initComponents() throws IOException, UnknownHostException { + emoSpeakPanel1 = new EmoSpeakPanel(true, System.getProperty("server.host", "cling.dfki.uni-sb.de"), Integer.getInteger( + "server.port", 59125).intValue()); - addWindowListener(new java.awt.event.WindowAdapter() { - public void windowClosing(java.awt.event.WindowEvent evt) { - exitForm(evt); - } - }); + getContentPane().setLayout(new java.awt.FlowLayout()); - getContentPane().add(emoSpeakPanel1); + addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosing(java.awt.event.WindowEvent evt) { + exitForm(evt); + } + }); - pack(); - java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); - setSize(new java.awt.Dimension(550, 630)); - setLocation((screenSize.width-550)/2,(screenSize.height-630)/2); - } - - /** Exit the Application */ - private void exitForm(java.awt.event.WindowEvent evt) { - emoSpeakPanel1.requestExit(); - System.exit(0); - } + getContentPane().add(emoSpeakPanel1); + + pack(); + java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); + setSize(new java.awt.Dimension(550, 630)); + setLocation((screenSize.width - 550) / 2, (screenSize.height - 630) / 2); + } + + /** Exit the Application */ + private void exitForm(java.awt.event.WindowEvent evt) { + emoSpeakPanel1.requestExit(); + System.exit(0); + } + + /** + * @param args + * the command line arguments + */ + public static void main(String args[]) throws Exception { + new EmoSpeak().setVisible(true); + } + + // Variables declaration - do not modify + private marytts.tools.emospeak.EmoSpeakPanel emoSpeakPanel1; + // End of variables declaration - /** - * @param args the command line arguments - */ - public static void main(String args[]) throws Exception { - new EmoSpeak().setVisible(true); - } - - - // Variables declaration - do not modify - private marytts.tools.emospeak.EmoSpeakPanel emoSpeakPanel1; - // End of variables declaration - } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakApplet.java b/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakApplet.java index 4723a4d6..eb075000 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakApplet.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakApplet.java @@ -19,47 +19,44 @@ */ package marytts.tools.emospeak; - /** - * - * @author schroed + * + * @author schroed */ public class EmoSpeakApplet extends javax.swing.JApplet { - - public void init() { - initComponents(); - emoSpeakPanel1.initialiseMenu(); - } - - /** This method is called from within the init() method to - * initialize the form. - */ - private void initComponents() { - String host = getCodeBase().getHost(); - if (host == null || host.equals("")) { - host = "localhost"; - } - try { - emoSpeakPanel1 = new EmoSpeakPanel(false, host, 59125); - } catch (Exception e) { - System.err.println("Cannot initialise EmoSpeakPanel:"); - e.printStackTrace(); - } + public void init() { + initComponents(); + emoSpeakPanel1.initialiseMenu(); + } - getContentPane().setLayout(new java.awt.FlowLayout()); + /** + * This method is called from within the init() method to initialize the form. + */ + private void initComponents() { + String host = getCodeBase().getHost(); + if (host == null || host.equals("")) { + host = "localhost"; + } + try { + emoSpeakPanel1 = new EmoSpeakPanel(false, host, 59125); + } catch (Exception e) { + System.err.println("Cannot initialise EmoSpeakPanel:"); + e.printStackTrace(); + } - getContentPane().add(emoSpeakPanel1); + getContentPane().setLayout(new java.awt.FlowLayout()); - } - - - // Variables declaration - private EmoSpeakPanel emoSpeakPanel1; - // End of variables declaration - - public void destroy() { - emoSpeakPanel1.requestExit(); - } + getContentPane().add(emoSpeakPanel1); + + } + + // Variables declaration + private EmoSpeakPanel emoSpeakPanel1; + + // End of variables declaration + + public void destroy() { + emoSpeakPanel1.requestExit(); + } } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakPanel.java b/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakPanel.java index 2661883a..d1cdddc9 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakPanel.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/EmoSpeakPanel.java @@ -47,349 +47,343 @@ import javax.swing.JRootPane; import marytts.client.MaryClient; import marytts.util.http.Address; - /** - * - * @author schroed + * + * @author schroed */ -public class EmoSpeakPanel extends javax.swing.JPanel -implements AudioFileReceiver, ProsodyXMLDisplayer -{ - private int r=1; - private EmoTransformer emoTransformer; - - - /* -------------------- Data and Processing stuff -------------------- */ - private AsynchronousThreadedMaryClient asynchronousSynthesiser; - private MaryClient synchronousSynthesiser; - private AudioInputStream currentAudio = null; - private AudioInputStream nextAudio = null; - private Clip clip = null; - private boolean synthesiseAsynchronously; - private String maryServerHost; - private int maryServerPort; - private Map voicesByLocale; // map locale to Vectors of MaryClient.Voice objects - boolean haveGerman = false; - private Map sampleTextsByLocale; // map locale to Vectors of Strings - private Map localeByDisplayLanguage; // map display language to locale - - - /** Creates new form EmoSpeakPanel */ - public EmoSpeakPanel(boolean synthesiseAsynchronously, - String maryServerHost, int maryServerPort) - throws IOException, UnknownHostException { - this.synthesiseAsynchronously = synthesiseAsynchronously; - this.maryServerHost = maryServerHost; - this.maryServerPort = maryServerPort; - synchronized (this) { +public class EmoSpeakPanel extends javax.swing.JPanel implements AudioFileReceiver, ProsodyXMLDisplayer { + private int r = 1; + private EmoTransformer emoTransformer; + + /* -------------------- Data and Processing stuff -------------------- */ + private AsynchronousThreadedMaryClient asynchronousSynthesiser; + private MaryClient synchronousSynthesiser; + private AudioInputStream currentAudio = null; + private AudioInputStream nextAudio = null; + private Clip clip = null; + private boolean synthesiseAsynchronously; + private String maryServerHost; + private int maryServerPort; + private Map voicesByLocale; // map locale to Vectors of MaryClient.Voice objects + boolean haveGerman = false; + private Map sampleTextsByLocale; // map locale to Vectors of Strings + private Map localeByDisplayLanguage; // map display language to locale + + /** Creates new form EmoSpeakPanel */ + public EmoSpeakPanel(boolean synthesiseAsynchronously, String maryServerHost, int maryServerPort) throws IOException, + UnknownHostException { + this.synthesiseAsynchronously = synthesiseAsynchronously; + this.maryServerHost = maryServerHost; + this.maryServerPort = maryServerPort; + synchronized (this) { initComponents(); customInitComponents(); - } - } - - /** Call this in order to use the emospeakpanel menu */ - public void initialiseMenu() { - JRootPane rp = getRootPane(); - if (rp != null) rp.setJMenuBar(jMenuBar1); - } + } + } - public TwoDimensionalModel feeltraceModel() { - return ftPanel.feeltraceModel(); - } - - public BoundedRangeModel powerModel() { - return ftPanel.powerModel(); - } + /** Call this in order to use the emospeakpanel menu */ + public void initialiseMenu() { + JRootPane rp = getRootPane(); + if (rp != null) + rp.setJMenuBar(jMenuBar1); + } - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - private void initComponents() {//GEN-BEGIN:initComponents - java.awt.GridBagConstraints gridBagConstraints; + public TwoDimensionalModel feeltraceModel() { + return ftPanel.feeltraceModel(); + } - audioPanel = new javax.swing.JPanel(); - lVoice = new javax.swing.JLabel(); - cbVoice = new javax.swing.JComboBox(); - bPlay = new javax.swing.JButton(); - dimensionValuePanel = new javax.swing.JPanel(); - lActivationValue = new javax.swing.JLabel(); - tfActivationValue = new javax.swing.JTextField(); - lEvaluationValue = new javax.swing.JLabel(); - tfEvaluationValue = new javax.swing.JTextField(); - lPowerValue = new javax.swing.JLabel(); - tfPowerValue = new javax.swing.JTextField(); - inputTextPanel = new javax.swing.JPanel(); - lInputText = new javax.swing.JLabel(); - cbInputText = new javax.swing.JComboBox(); - ftPanel = new JFeeltracePanel(); - lProsodyXML = new javax.swing.JLabel(); - jScrollPane1 = new javax.swing.JScrollPane(); - tpProsodyXML = new javax.swing.JTextPane(); - jMenuBar1 = new javax.swing.JMenuBar(); - optionsMenu = new javax.swing.JMenu(); - showPowerMenuItem = new javax.swing.JCheckBoxMenuItem(); - showMaryXMLMenuItem = new javax.swing.JCheckBoxMenuItem(); + public BoundedRangeModel powerModel() { + return ftPanel.powerModel(); + } - setLayout(new java.awt.GridBagLayout()); + /** + * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of + * this method is always regenerated by the Form Editor. + */ + private void initComponents() {// GEN-BEGIN:initComponents + java.awt.GridBagConstraints gridBagConstraints; - // Manually added, Feb. 2006: - cbLanguage = new JComboBox(); - cbLanguage.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cbLanguageItemStateChanged(evt); - } - }); - audioPanel.add(cbLanguage); - lVoice.setText("Voice:"); - audioPanel.add(lVoice); + audioPanel = new javax.swing.JPanel(); + lVoice = new javax.swing.JLabel(); + cbVoice = new javax.swing.JComboBox(); + bPlay = new javax.swing.JButton(); + dimensionValuePanel = new javax.swing.JPanel(); + lActivationValue = new javax.swing.JLabel(); + tfActivationValue = new javax.swing.JTextField(); + lEvaluationValue = new javax.swing.JLabel(); + tfEvaluationValue = new javax.swing.JTextField(); + lPowerValue = new javax.swing.JLabel(); + tfPowerValue = new javax.swing.JTextField(); + inputTextPanel = new javax.swing.JPanel(); + lInputText = new javax.swing.JLabel(); + cbInputText = new javax.swing.JComboBox(); + ftPanel = new JFeeltracePanel(); + lProsodyXML = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + tpProsodyXML = new javax.swing.JTextPane(); + jMenuBar1 = new javax.swing.JMenuBar(); + optionsMenu = new javax.swing.JMenu(); + showPowerMenuItem = new javax.swing.JCheckBoxMenuItem(); + showMaryXMLMenuItem = new javax.swing.JCheckBoxMenuItem(); - cbVoice.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cbVoiceItemStateChanged(evt); - } - }); + setLayout(new java.awt.GridBagLayout()); - audioPanel.add(cbVoice); + // Manually added, Feb. 2006: + cbLanguage = new JComboBox(); + cbLanguage.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cbLanguageItemStateChanged(evt); + } + }); + audioPanel.add(cbLanguage); + lVoice.setText("Voice:"); + audioPanel.add(lVoice); - bPlay.setText("Play"); - bPlay.setMnemonic('P'); - bPlay.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - bPlayActionPerformed(evt); - } - }); + cbVoice.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cbVoiceItemStateChanged(evt); + } + }); - audioPanel.add(bPlay); + audioPanel.add(cbVoice); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 3; - gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10); - gridBagConstraints.anchor = GridBagConstraints.WEST; - add(audioPanel, gridBagConstraints); + bPlay.setText("Play"); + bPlay.setMnemonic('P'); + bPlay.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + bPlayActionPerformed(evt); + } + }); - dimensionValuePanel.setLayout(new java.awt.GridLayout(3, 2)); + audioPanel.add(bPlay); - lActivationValue.setText("Activation"); - dimensionValuePanel.add(lActivationValue); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 3; + gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10); + gridBagConstraints.anchor = GridBagConstraints.WEST; + add(audioPanel, gridBagConstraints); - tfActivationValue.setText("0"); - tfActivationValue.setPreferredSize(new java.awt.Dimension(40, 21)); - tfActivationValue.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - tfActivationValueActionPerformed(evt); - } - }); + dimensionValuePanel.setLayout(new java.awt.GridLayout(3, 2)); - tfActivationValue.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - tfActivationValueFocusLost(evt); - } - }); + lActivationValue.setText("Activation"); + dimensionValuePanel.add(lActivationValue); - dimensionValuePanel.add(tfActivationValue); + tfActivationValue.setText("0"); + tfActivationValue.setPreferredSize(new java.awt.Dimension(40, 21)); + tfActivationValue.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tfActivationValueActionPerformed(evt); + } + }); - lEvaluationValue.setText("Evaluation"); - dimensionValuePanel.add(lEvaluationValue); + tfActivationValue.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + tfActivationValueFocusLost(evt); + } + }); - tfEvaluationValue.setText("0"); - tfEvaluationValue.setPreferredSize(new java.awt.Dimension(40, 21)); - tfEvaluationValue.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - tfEvaluationValueActionPerformed(evt); - } - }); + dimensionValuePanel.add(tfActivationValue); - tfEvaluationValue.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - tfEvaluationValueFocusLost(evt); - } - }); + lEvaluationValue.setText("Evaluation"); + dimensionValuePanel.add(lEvaluationValue); - dimensionValuePanel.add(tfEvaluationValue); + tfEvaluationValue.setText("0"); + tfEvaluationValue.setPreferredSize(new java.awt.Dimension(40, 21)); + tfEvaluationValue.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tfEvaluationValueActionPerformed(evt); + } + }); - lPowerValue.setText("Power"); - dimensionValuePanel.add(lPowerValue); + tfEvaluationValue.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + tfEvaluationValueFocusLost(evt); + } + }); - tfPowerValue.setText("0"); - tfPowerValue.setPreferredSize(new java.awt.Dimension(40, 21)); - tfPowerValue.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - tfPowerValueActionPerformed(evt); - } - }); + dimensionValuePanel.add(tfEvaluationValue); - tfPowerValue.addFocusListener(new java.awt.event.FocusAdapter() { - public void focusLost(java.awt.event.FocusEvent evt) { - tfPowerValueFocusLost(evt); - } - }); + lPowerValue.setText("Power"); + dimensionValuePanel.add(lPowerValue); - dimensionValuePanel.add(tfPowerValue); + tfPowerValue.setText("0"); + tfPowerValue.setPreferredSize(new java.awt.Dimension(40, 21)); + tfPowerValue.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + tfPowerValueActionPerformed(evt); + } + }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridheight = 3; - gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 4); - add(dimensionValuePanel, gridBagConstraints); + tfPowerValue.addFocusListener(new java.awt.event.FocusAdapter() { + public void focusLost(java.awt.event.FocusEvent evt) { + tfPowerValueFocusLost(evt); + } + }); - lInputText.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); - lInputText.setText("Text:"); - inputTextPanel.add(lInputText); + dimensionValuePanel.add(tfPowerValue); - cbInputText.setEditable(true); - cbInputText.setFont(new java.awt.Font("Dialog", 0, 10)); - cbInputText.setToolTipText("Type or select the text to be spoken."); - cbInputText.setPreferredSize(new java.awt.Dimension(350, 26)); - cbInputText.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cbInputTextActionPerformed(evt); - } - }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridheight = 3; + gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 4); + add(dimensionValuePanel, gridBagConstraints); - cbInputText.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - cbInputTextItemStateChanged(evt); - } - }); + lInputText.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + lInputText.setText("Text:"); + inputTextPanel.add(lInputText); - inputTextPanel.add(cbInputText); + cbInputText.setEditable(true); + cbInputText.setFont(new java.awt.Font("Dialog", 0, 10)); + cbInputText.setToolTipText("Type or select the text to be spoken."); + cbInputText.setPreferredSize(new java.awt.Dimension(350, 26)); + cbInputText.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + cbInputTextActionPerformed(evt); + } + }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; - add(inputTextPanel, gridBagConstraints); + cbInputText.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + cbInputTextItemStateChanged(evt); + } + }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridwidth = 2; - gridBagConstraints.weightx = 0.2; - gridBagConstraints.weighty = 0.2; - add(ftPanel, gridBagConstraints); + inputTextPanel.add(cbInputText); - lProsodyXML.setText("Prosody XML:"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 4; - add(lProsodyXML, gridBagConstraints); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; + add(inputTextPanel, gridBagConstraints); - jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); - jScrollPane1.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - jScrollPane1.setPreferredSize(new java.awt.Dimension(400, 100)); - tpProsodyXML.setBorder(new javax.swing.border.EtchedBorder()); - tpProsodyXML.setEditable(false); - tpProsodyXML.setPreferredSize(new java.awt.Dimension(400, 100)); - jScrollPane1.setViewportView(tpProsodyXML); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridwidth = 2; + gridBagConstraints.weightx = 0.2; + gridBagConstraints.weighty = 0.2; + add(ftPanel, gridBagConstraints); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 5; - gridBagConstraints.gridwidth = 2; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 0.2; - gridBagConstraints.weighty = 0.2; - gridBagConstraints.insets = new java.awt.Insets(4, 2, 4, 2); - add(jScrollPane1, gridBagConstraints); + lProsodyXML.setText("Prosody XML:"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 4; + add(lProsodyXML, gridBagConstraints); - optionsMenu.setText("Options"); - optionsMenu.setMnemonic('O'); - optionsMenu.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - optionsMenuActionPerformed(evt); - } - }); + jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane1.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + jScrollPane1.setPreferredSize(new java.awt.Dimension(400, 100)); + tpProsodyXML.setBorder(new javax.swing.border.EtchedBorder()); + tpProsodyXML.setEditable(false); + tpProsodyXML.setPreferredSize(new java.awt.Dimension(400, 100)); + jScrollPane1.setViewportView(tpProsodyXML); - showPowerMenuItem.setSelected(true); - showPowerMenuItem.setText("Show Power"); - showPowerMenuItem.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - showPowerMenuItemItemStateChanged(evt); - } - }); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 5; + gridBagConstraints.gridwidth = 2; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 0.2; + gridBagConstraints.weighty = 0.2; + gridBagConstraints.insets = new java.awt.Insets(4, 2, 4, 2); + add(jScrollPane1, gridBagConstraints); - optionsMenu.add(showPowerMenuItem); - showMaryXMLMenuItem.setSelected(true); - showMaryXMLMenuItem.setText("Show Prosody XML"); - showMaryXMLMenuItem.addItemListener(new java.awt.event.ItemListener() { - public void itemStateChanged(java.awt.event.ItemEvent evt) { - showMaryXMLMenuItemItemStateChanged(evt); - } - }); + optionsMenu.setText("Options"); + optionsMenu.setMnemonic('O'); + optionsMenu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + optionsMenuActionPerformed(evt); + } + }); - optionsMenu.add(showMaryXMLMenuItem); - jMenuBar1.add(optionsMenu); + showPowerMenuItem.setSelected(true); + showPowerMenuItem.setText("Show Power"); + showPowerMenuItem.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + showPowerMenuItemItemStateChanged(evt); + } + }); - }//GEN-END:initComponents + optionsMenu.add(showPowerMenuItem); + showMaryXMLMenuItem.setSelected(true); + showMaryXMLMenuItem.setText("Show Prosody XML"); + showMaryXMLMenuItem.addItemListener(new java.awt.event.ItemListener() { + public void itemStateChanged(java.awt.event.ItemEvent evt) { + showMaryXMLMenuItemItemStateChanged(evt); + } + }); - private void tfActivationValueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tfActivationValueActionPerformed - updateFeeltraceModelFromTextFields(); - }//GEN-LAST:event_tfActivationValueActionPerformed + optionsMenu.add(showMaryXMLMenuItem); + jMenuBar1.add(optionsMenu); - private void tfEvaluationValueFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_tfEvaluationValueFocusLost - updateFeeltraceModelFromTextFields(); - }//GEN-LAST:event_tfEvaluationValueFocusLost + }// GEN-END:initComponents - private void bPlayActionPerformed(java.awt.event.ActionEvent evt) { - if (bPlay.getText().equals("Play")) { - try { - preparePlayAudio(); - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(this, e.getMessage(), "Cannot play audio", JOptionPane.ERROR_MESSAGE); - return; - } - bPlay.setText("Stop"); - playAudio(); - } else { - bPlay.setText("Play"); - if (clip != null) { - clip.stop(); - } - } - } + private void tfActivationValueActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tfActivationValueActionPerformed + updateFeeltraceModelFromTextFields(); + }// GEN-LAST:event_tfActivationValueActionPerformed - private void optionsMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_optionsMenuActionPerformed - // Add your handling code here: - }//GEN-LAST:event_optionsMenuActionPerformed + private void tfEvaluationValueFocusLost(java.awt.event.FocusEvent evt) {// GEN-FIRST:event_tfEvaluationValueFocusLost + updateFeeltraceModelFromTextFields(); + }// GEN-LAST:event_tfEvaluationValueFocusLost - private void cbInputTextItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cbInputTextItemStateChanged - if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected - requestUpdateProsodyXML(); - } - }//GEN-LAST:event_cbInputTextItemStateChanged + private void bPlayActionPerformed(java.awt.event.ActionEvent evt) { + if (bPlay.getText().equals("Play")) { + try { + preparePlayAudio(); + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(this, e.getMessage(), "Cannot play audio", JOptionPane.ERROR_MESSAGE); + return; + } + bPlay.setText("Stop"); + playAudio(); + } else { + bPlay.setText("Play"); + if (clip != null) { + clip.stop(); + } + } + } - // Manually added, Feb. 2006 - private void cbLanguageItemStateChanged(java.awt.event.ItemEvent evt) { - if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected - updateVoices(); - updateSampleTexts(); - } - } + private void optionsMenuActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_optionsMenuActionPerformed + // Add your handling code here: + }// GEN-LAST:event_optionsMenuActionPerformed - private Vector readSampleTexts(Locale locale) - { - Vector texts = new Vector(); - try { - BufferedReader br = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("sampletexts_"+locale.getLanguage()+".txt"),"UTF-8")); - String line; - while ((line = br.readLine()) != null) { - if (!line.trim().equals("")) - texts.add(line); - } - } catch (Exception e) {} - return texts; - } + private void cbInputTextItemStateChanged(java.awt.event.ItemEvent evt) {// GEN-FIRST:event_cbInputTextItemStateChanged + if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected + requestUpdateProsodyXML(); + } + }// GEN-LAST:event_cbInputTextItemStateChanged - private Locale getSelectedLanguage() - { - String displayLanguage = (String) cbLanguage.getSelectedItem(); - return (Locale) localeByDisplayLanguage.get(displayLanguage); - } + // Manually added, Feb. 2006 + private void cbLanguageItemStateChanged(java.awt.event.ItemEvent evt) { + if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected + updateVoices(); + updateSampleTexts(); + } + } - private void updateVoices() + private Vector readSampleTexts(Locale locale) { + Vector texts = new Vector(); + try { + BufferedReader br = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream( + "sampletexts_" + locale.getLanguage() + ".txt"), "UTF-8")); + String line; + while ((line = br.readLine()) != null) { + if (!line.trim().equals("")) + texts.add(line); + } + } catch (Exception e) { + } + return texts; + } + + private Locale getSelectedLanguage() { + String displayLanguage = (String) cbLanguage.getSelectedItem(); + return (Locale) localeByDisplayLanguage.get(displayLanguage); + } + + private void updateVoices() { Locale locale = getSelectedLanguage(); cbVoice.removeAllItems(); @@ -403,8 +397,8 @@ implements AudioFileReceiver, ProsodyXMLDisplayer } } } - - private void updateSampleTexts() + + private void updateSampleTexts() { Locale locale = getSelectedLanguage(); cbInputText.removeAllItems(); @@ -421,223 +415,224 @@ implements AudioFileReceiver, ProsodyXMLDisplayer cbInputText.setSelectedIndex(0); } - private void showPowerMenuItemItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_showPowerMenuItemItemStateChanged - if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected - ftPanel.setShowPower(true); - } else { // deselected - ftPanel.setShowPower(false); - bPlay.requestFocusInWindow(); - } - ftPanel.verifyPowerVisible(); - verifyPowerVisible(); - }//GEN-LAST:event_showPowerMenuItemItemStateChanged + private void showPowerMenuItemItemStateChanged(java.awt.event.ItemEvent evt) {// GEN-FIRST:event_showPowerMenuItemItemStateChanged + if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected + ftPanel.setShowPower(true); + } else { // deselected + ftPanel.setShowPower(false); + bPlay.requestFocusInWindow(); + } + ftPanel.verifyPowerVisible(); + verifyPowerVisible(); + }// GEN-LAST:event_showPowerMenuItemItemStateChanged - private void showMaryXMLMenuItemItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_showMaryXMLMenuItemItemStateChanged - if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected - jScrollPane1.setVisible(true); - lProsodyXML.setVisible(true); - } else { // deselected - jScrollPane1.setVisible(false); - lProsodyXML.setVisible(false); - bPlay.requestFocusInWindow(); - } - }//GEN-LAST:event_showMaryXMLMenuItemItemStateChanged + private void showMaryXMLMenuItemItemStateChanged(java.awt.event.ItemEvent evt) {// GEN-FIRST:event_showMaryXMLMenuItemItemStateChanged + if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected + jScrollPane1.setVisible(true); + lProsodyXML.setVisible(true); + } else { // deselected + jScrollPane1.setVisible(false); + lProsodyXML.setVisible(false); + bPlay.requestFocusInWindow(); + } + }// GEN-LAST:event_showMaryXMLMenuItemItemStateChanged - private void cbVoiceItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cbVoiceItemStateChanged - if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected - requestUpdateProsodyXML(); - } - }//GEN-LAST:event_cbVoiceItemStateChanged + private void cbVoiceItemStateChanged(java.awt.event.ItemEvent evt) {// GEN-FIRST:event_cbVoiceItemStateChanged + if (evt.getStateChange() == java.awt.event.ItemEvent.SELECTED) { // new item selected + requestUpdateProsodyXML(); + } + }// GEN-LAST:event_cbVoiceItemStateChanged - private void cbInputTextActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbInputTextActionPerformed - Object item = cbInputText.getSelectedItem(); - if (((DefaultComboBoxModel)cbInputText.getModel()).getIndexOf(item) == -1) { - // new sentence typed in, remember it - cbInputText.addItem(item); - } - requestUpdateProsodyXML(); - }//GEN-LAST:event_cbInputTextActionPerformed + private void cbInputTextActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_cbInputTextActionPerformed + Object item = cbInputText.getSelectedItem(); + if (((DefaultComboBoxModel) cbInputText.getModel()).getIndexOf(item) == -1) { + // new sentence typed in, remember it + cbInputText.addItem(item); + } + requestUpdateProsodyXML(); + }// GEN-LAST:event_cbInputTextActionPerformed - private void tfPowerValueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tfPowerValueActionPerformed - updatePowerModelFromTextFields(); - }//GEN-LAST:event_tfPowerValueActionPerformed + private void tfPowerValueActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tfPowerValueActionPerformed + updatePowerModelFromTextFields(); + }// GEN-LAST:event_tfPowerValueActionPerformed - private void tfEvaluationValueActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_tfEvaluationValueActionPerformed - updateFeeltraceModelFromTextFields(); - }//GEN-LAST:event_tfEvaluationValueActionPerformed + private void tfEvaluationValueActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_tfEvaluationValueActionPerformed + updateFeeltraceModelFromTextFields(); + }// GEN-LAST:event_tfEvaluationValueActionPerformed - private void tfActivationValueFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_tfActivationValueFocusLost - updateFeeltraceModelFromTextFields(); - }//GEN-LAST:event_tfActivationValueFocusLost + private void tfActivationValueFocusLost(java.awt.event.FocusEvent evt) {// GEN-FIRST:event_tfActivationValueFocusLost + updateFeeltraceModelFromTextFields(); + }// GEN-LAST:event_tfActivationValueFocusLost - private void tfPowerValueFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_tfPowerValueFocusLost - updatePowerModelFromTextFields(); - }//GEN-LAST:event_tfPowerValueFocusLost - - public void requestExit() { - emoTransformer.requestExit(); - if (synthesiseAsynchronously) - asynchronousSynthesiser.requestExit(); - } + private void tfPowerValueFocusLost(java.awt.event.FocusEvent evt) {// GEN-FIRST:event_tfPowerValueFocusLost + updatePowerModelFromTextFields(); + }// GEN-LAST:event_tfPowerValueFocusLost - private synchronized void customInitComponents() - throws IOException, UnknownHostException { - if (synthesiseAsynchronously) { - if (maryServerHost == null) { - asynchronousSynthesiser = new AsynchronousThreadedMaryClient(this); - } else { - asynchronousSynthesiser = new AsynchronousThreadedMaryClient - (this, maryServerHost, maryServerPort, false, false); - } - asynchronousSynthesiser.start(); - } else { - if (maryServerHost == null) { - synchronousSynthesiser = MaryClient.getMaryClient(); - } else { - synchronousSynthesiser = MaryClient.getMaryClient(new Address(maryServerHost, maryServerPort), false, false); - } - } - - try { - emoTransformer = new EmoTransformer(this); - } catch (Exception ex) { - ex.printStackTrace(); - } - emoTransformer.start(); - - verifyPowerVisible(); - feeltraceModel().addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent e) { - updateFeeltraceDisplays(); - requestUpdateProsodyXML(); - } - }); - if (ftPanel.showPower()) { - powerModel().addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent e) { - updatePowerDisplays(); - requestUpdateProsodyXML(); - } - }); - } + public void requestExit() { + emoTransformer.requestExit(); + if (synthesiseAsynchronously) + asynchronousSynthesiser.requestExit(); + } - Vector voiceInfo; - if (synthesiseAsynchronously) { - voiceInfo = asynchronousSynthesiser.getServerVoices(); - } else { - voiceInfo = synchronousSynthesiser.getGeneralDomainVoices(); - } - - if (voiceInfo == null) { - String host; - int port; - if (synthesiseAsynchronously) { - host = asynchronousSynthesiser.getHost(); - port = asynchronousSynthesiser.getPort(); - } else { - host = synchronousSynthesiser.getHost(); - port = synchronousSynthesiser.getPort(); - } - JOptionPane.showMessageDialog(null, "Cannot start EmoSpeak: Server "+host+":"+port+" has no general domain voices!", - "No voices available", JOptionPane.ERROR_MESSAGE); - System.exit(1); - } - - voicesByLocale = new HashMap(); - sampleTextsByLocale = new HashMap(); - localeByDisplayLanguage = new HashMap(); - for (Iterator it = voiceInfo.iterator(); it.hasNext(); ) { - MaryClient.Voice v = (MaryClient.Voice) it.next(); - if (!voicesByLocale.containsKey(v.getLocale())) { - voicesByLocale.put(v.getLocale(), new Vector()); - } - Vector localeVoices = (Vector) voicesByLocale.get(v.getLocale()); - localeVoices.add(v); - if (v.getLocale().equals(Locale.GERMAN)) haveGerman = true; - } - - for (Iterator it = voicesByLocale.keySet().iterator(); it.hasNext(); ) { - Locale locale = (Locale) it.next(); - sampleTextsByLocale.put(locale, readSampleTexts(locale)); - localeByDisplayLanguage.put(locale.getDisplayLanguage(), locale); - cbLanguage.addItem(locale.getDisplayLanguage()); - } - if (haveGerman) cbLanguage.setSelectedItem(Locale.GERMAN); - updateVoices(); - updateSampleTexts(); - } - - private void updateFeeltraceModelFromTextFields() { - boolean validA = false; - boolean validE = false; - int A = 0; - int E = 0; - try { - A = Integer.parseInt(tfActivationValue.getText()); - if (feeltraceModel().getMinY() <= A && A <= feeltraceModel().getMaxY()) { - validA = true; - } - } catch (NumberFormatException e) {} - try { - E = Integer.parseInt(tfEvaluationValue.getText()); - if (feeltraceModel().getMinX() <= E && E <= feeltraceModel().getMaxX()) { - validE = true; - } - } catch (NumberFormatException e) {} - int newA = validA ? A : feeltraceModel().getY(); - int newE = validE ? E : feeltraceModel().getX(); - feeltraceModel().setXY(newE, newA); - } + private synchronized void customInitComponents() throws IOException, UnknownHostException { + if (synthesiseAsynchronously) { + if (maryServerHost == null) { + asynchronousSynthesiser = new AsynchronousThreadedMaryClient(this); + } else { + asynchronousSynthesiser = new AsynchronousThreadedMaryClient(this, maryServerHost, maryServerPort, false, false); + } + asynchronousSynthesiser.start(); + } else { + if (maryServerHost == null) { + synchronousSynthesiser = MaryClient.getMaryClient(); + } else { + synchronousSynthesiser = MaryClient.getMaryClient(new Address(maryServerHost, maryServerPort), false, false); + } + } - private void updatePowerModelFromTextFields() { - boolean valid = false; - int value = 0; - try { - value = Integer.parseInt(tfPowerValue.getText()); - if (value >= powerModel().getMinimum() && - value <= powerModel().getMaximum()) { - valid = true; - } - } catch (NumberFormatException e) {} - if (valid) - // adopt new value - powerModel().setValue(value); - else - // reset display to old value - tfPowerValue.setText(String.valueOf(powerModel().getValue())); + try { + emoTransformer = new EmoTransformer(this); + } catch (Exception ex) { + ex.printStackTrace(); + } + emoTransformer.start(); - } + verifyPowerVisible(); + feeltraceModel().addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent e) { + updateFeeltraceDisplays(); + requestUpdateProsodyXML(); + } + }); + if (ftPanel.showPower()) { + powerModel().addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent e) { + updatePowerDisplays(); + requestUpdateProsodyXML(); + } + }); + } - - protected void paintComponent(java.awt.Graphics graphics) { - verifyPowerVisible(); - super.paintComponent(graphics); - } - - private void verifyPowerVisible() { - lPowerValue.setVisible(ftPanel.showPower()); - tfPowerValue.setVisible(ftPanel.showPower()); - } - - private void updateFeeltraceDisplays() { - tfActivationValue.setText(String.valueOf(feeltraceModel().getY())); - tfEvaluationValue.setText(String.valueOf(feeltraceModel().getX())); - } - - private void updatePowerDisplays() { - tfPowerValue.setText(String.valueOf(powerModel().getValue())); - } - - private void requestUpdateProsodyXML() { - Object selectedText = cbInputText.getSelectedItem(); - if (selectedText == null) return; - String text = selectedText.toString(); - emoTransformer.setEmotionValues(feeltraceModel().getY(), - feeltraceModel().getX(), powerModel().getValue(), - text, getSelectedLanguage(), r++); - } - - public synchronized void updateProsodyXML(String prosodyxmlString, int r1) { + Vector voiceInfo; + if (synthesiseAsynchronously) { + voiceInfo = asynchronousSynthesiser.getServerVoices(); + } else { + voiceInfo = synchronousSynthesiser.getGeneralDomainVoices(); + } + + if (voiceInfo == null) { + String host; + int port; + if (synthesiseAsynchronously) { + host = asynchronousSynthesiser.getHost(); + port = asynchronousSynthesiser.getPort(); + } else { + host = synchronousSynthesiser.getHost(); + port = synchronousSynthesiser.getPort(); + } + JOptionPane.showMessageDialog(null, "Cannot start EmoSpeak: Server " + host + ":" + port + + " has no general domain voices!", "No voices available", JOptionPane.ERROR_MESSAGE); + System.exit(1); + } + + voicesByLocale = new HashMap(); + sampleTextsByLocale = new HashMap(); + localeByDisplayLanguage = new HashMap(); + for (Iterator it = voiceInfo.iterator(); it.hasNext();) { + MaryClient.Voice v = (MaryClient.Voice) it.next(); + if (!voicesByLocale.containsKey(v.getLocale())) { + voicesByLocale.put(v.getLocale(), new Vector()); + } + Vector localeVoices = (Vector) voicesByLocale.get(v.getLocale()); + localeVoices.add(v); + if (v.getLocale().equals(Locale.GERMAN)) + haveGerman = true; + } + + for (Iterator it = voicesByLocale.keySet().iterator(); it.hasNext();) { + Locale locale = (Locale) it.next(); + sampleTextsByLocale.put(locale, readSampleTexts(locale)); + localeByDisplayLanguage.put(locale.getDisplayLanguage(), locale); + cbLanguage.addItem(locale.getDisplayLanguage()); + } + if (haveGerman) + cbLanguage.setSelectedItem(Locale.GERMAN); + updateVoices(); + updateSampleTexts(); + } + + private void updateFeeltraceModelFromTextFields() { + boolean validA = false; + boolean validE = false; + int A = 0; + int E = 0; + try { + A = Integer.parseInt(tfActivationValue.getText()); + if (feeltraceModel().getMinY() <= A && A <= feeltraceModel().getMaxY()) { + validA = true; + } + } catch (NumberFormatException e) { + } + try { + E = Integer.parseInt(tfEvaluationValue.getText()); + if (feeltraceModel().getMinX() <= E && E <= feeltraceModel().getMaxX()) { + validE = true; + } + } catch (NumberFormatException e) { + } + int newA = validA ? A : feeltraceModel().getY(); + int newE = validE ? E : feeltraceModel().getX(); + feeltraceModel().setXY(newE, newA); + } + + private void updatePowerModelFromTextFields() { + boolean valid = false; + int value = 0; + try { + value = Integer.parseInt(tfPowerValue.getText()); + if (value >= powerModel().getMinimum() && value <= powerModel().getMaximum()) { + valid = true; + } + } catch (NumberFormatException e) { + } + if (valid) + // adopt new value + powerModel().setValue(value); + else + // reset display to old value + tfPowerValue.setText(String.valueOf(powerModel().getValue())); + + } + + protected void paintComponent(java.awt.Graphics graphics) { + verifyPowerVisible(); + super.paintComponent(graphics); + } + + private void verifyPowerVisible() { + lPowerValue.setVisible(ftPanel.showPower()); + tfPowerValue.setVisible(ftPanel.showPower()); + } + + private void updateFeeltraceDisplays() { + tfActivationValue.setText(String.valueOf(feeltraceModel().getY())); + tfEvaluationValue.setText(String.valueOf(feeltraceModel().getX())); + } + + private void updatePowerDisplays() { + tfPowerValue.setText(String.valueOf(powerModel().getValue())); + } + + private void requestUpdateProsodyXML() { + Object selectedText = cbInputText.getSelectedItem(); + if (selectedText == null) + return; + String text = selectedText.toString(); + emoTransformer.setEmotionValues(feeltraceModel().getY(), feeltraceModel().getX(), powerModel().getValue(), text, + getSelectedLanguage(), r++); + } + + public synchronized void updateProsodyXML(String prosodyxmlString, int r1) { tpProsodyXML.setText(prosodyxmlString); if (synthesiseAsynchronously) { MaryClient.Voice maryClientVoice = (MaryClient.Voice) cbVoice.getSelectedItem(); @@ -645,101 +640,88 @@ implements AudioFileReceiver, ProsodyXMLDisplayer asynchronousSynthesiser.scheduleRequest(prosodyxmlString, maryClientVoice, r1); } } - - private void preparePlayAudio() throws Exception { - if (synthesiseAsynchronously) { - if (nextAudio != null) { - currentAudio = nextAudio; - nextAudio = null; - } - } else { // synthesise now - ByteArrayOutputStream os = new ByteArrayOutputStream(); - synchronousSynthesiser.process(tpProsodyXML.getText(), - "RAWMARYXML", - "AUDIO", - ((MaryClient.Voice) cbVoice.getSelectedItem()).getLocale().toString(), - "AU", - ((MaryClient.Voice) cbVoice.getSelectedItem()).name(), - os); - byte[] bytes = os.toByteArray(); - currentAudio = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes)); - } - if (currentAudio == null && (clip == null || !clip.isOpen())) { - bPlay.setEnabled(false); - throw new Exception("No audio data to play (did synthesis succeed?)"); - } - if (currentAudio != null) { - if (clip != null && clip.isOpen()) closeClip(); - // Create new clip - DataLine.Info info = - new DataLine.Info(Clip.class, currentAudio.getFormat()); - clip = (Clip) AudioSystem.getLine(info); - clip.addLineListener(new LineListener() { - public void update(LineEvent le) { - if (le.getType() == LineEvent.Type.STOP) { - closeAudio(); - } - } - }); - clip.open(currentAudio); - currentAudio.close(); - currentAudio = null; - } - // do this in particular for the previously played clips: - clip.setFramePosition(0); - // And now, clip.start() will play - } - - private void playAudio() { + + private void preparePlayAudio() throws Exception { + if (synthesiseAsynchronously) { + if (nextAudio != null) { + currentAudio = nextAudio; + nextAudio = null; + } + } else { // synthesise now + ByteArrayOutputStream os = new ByteArrayOutputStream(); + synchronousSynthesiser.process(tpProsodyXML.getText(), "RAWMARYXML", "AUDIO", + ((MaryClient.Voice) cbVoice.getSelectedItem()).getLocale().toString(), "AU", + ((MaryClient.Voice) cbVoice.getSelectedItem()).name(), os); + byte[] bytes = os.toByteArray(); + currentAudio = AudioSystem.getAudioInputStream(new ByteArrayInputStream(bytes)); + } + if (currentAudio == null && (clip == null || !clip.isOpen())) { + bPlay.setEnabled(false); + throw new Exception("No audio data to play (did synthesis succeed?)"); + } + if (currentAudio != null) { + if (clip != null && clip.isOpen()) + closeClip(); + // Create new clip + DataLine.Info info = new DataLine.Info(Clip.class, currentAudio.getFormat()); + clip = (Clip) AudioSystem.getLine(info); + clip.addLineListener(new LineListener() { + public void update(LineEvent le) { + if (le.getType() == LineEvent.Type.STOP) { + closeAudio(); + } + } + }); + clip.open(currentAudio); + currentAudio.close(); + currentAudio = null; + } + // do this in particular for the previously played clips: + clip.setFramePosition(0); + // And now, clip.start() will play + } + + private void playAudio() { assert clip != null && clip.isOpen(); clip.start(); } - - private void closeAudio() { - bPlay.setText("Play"); - } - - private void closeClip() { - // workaround for a bug in Linux-based Java VM from Sun: - if (!(System.getProperty("java.vendor").equals("Sun Microsystems Inc.") && - System.getProperty("os.name").equals("Linux"))) { - clip.close(); - } - } - - public void setNextAudio(javax.sound.sampled.AudioInputStream audioInputStream) { - nextAudio = audioInputStream; - } - - - - - - - - private javax.swing.JTextField tfPowerValue; - private javax.swing.JCheckBoxMenuItem showPowerMenuItem; - private javax.swing.JComboBox cbInputText; - private javax.swing.JLabel lPowerValue; - private javax.swing.JButton bPlay; - private javax.swing.JTextPane tpProsodyXML; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JCheckBoxMenuItem showMaryXMLMenuItem; - private javax.swing.JLabel lActivationValue; - private javax.swing.JPanel inputTextPanel; - private javax.swing.JTextField tfActivationValue; - private javax.swing.JLabel lVoice; - private javax.swing.JLabel lProsodyXML; - private javax.swing.JMenu optionsMenu; - private javax.swing.JPanel dimensionValuePanel; - private JFeeltracePanel ftPanel; - private javax.swing.JComboBox cbVoice; - private javax.swing.JPanel audioPanel; - private javax.swing.JLabel lInputText; - private javax.swing.JLabel lEvaluationValue; - private javax.swing.JMenuBar jMenuBar1; - private javax.swing.JTextField tfEvaluationValue; - private JComboBox cbLanguage; + private void closeAudio() { + bPlay.setText("Play"); + } + + private void closeClip() { + // workaround for a bug in Linux-based Java VM from Sun: + if (!(System.getProperty("java.vendor").equals("Sun Microsystems Inc.") && System.getProperty("os.name").equals("Linux"))) { + clip.close(); + } + } + + public void setNextAudio(javax.sound.sampled.AudioInputStream audioInputStream) { + nextAudio = audioInputStream; + } + + private javax.swing.JTextField tfPowerValue; + private javax.swing.JCheckBoxMenuItem showPowerMenuItem; + private javax.swing.JComboBox cbInputText; + private javax.swing.JLabel lPowerValue; + private javax.swing.JButton bPlay; + private javax.swing.JTextPane tpProsodyXML; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JCheckBoxMenuItem showMaryXMLMenuItem; + private javax.swing.JLabel lActivationValue; + private javax.swing.JPanel inputTextPanel; + private javax.swing.JTextField tfActivationValue; + private javax.swing.JLabel lVoice; + private javax.swing.JLabel lProsodyXML; + private javax.swing.JMenu optionsMenu; + private javax.swing.JPanel dimensionValuePanel; + private JFeeltracePanel ftPanel; + private javax.swing.JComboBox cbVoice; + private javax.swing.JPanel audioPanel; + private javax.swing.JLabel lInputText; + private javax.swing.JLabel lEvaluationValue; + private javax.swing.JMenuBar jMenuBar1; + private javax.swing.JTextField tfEvaluationValue; + private JComboBox cbLanguage; } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/EmoTransformer.java b/marytts-client/src/main/java/marytts/tools/emospeak/EmoTransformer.java index cb1b0268..b30ebfbc 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/EmoTransformer.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/EmoTransformer.java @@ -26,132 +26,119 @@ import javax.xml.transform.TransformerConfigurationException; import marytts.util.MaryUtils; - /** - * + * * @author Marc Schröder */ public class EmoTransformer extends Thread { - private int r; - private ProsodyXMLDisplayer emoSpeak; + private int r; + private ProsodyXMLDisplayer emoSpeak; - private javax.xml.transform.TransformerFactory tFactory = null; - private javax.xml.transform.Templates stylesheet = null; - private javax.xml.transform.Transformer transformer = null; - private javax.xml.parsers.DocumentBuilderFactory dbFactory = null; - private javax.xml.parsers.DocumentBuilder docBuilder = null; + private javax.xml.transform.TransformerFactory tFactory = null; + private javax.xml.transform.Templates stylesheet = null; + private javax.xml.transform.Transformer transformer = null; + private javax.xml.parsers.DocumentBuilderFactory dbFactory = null; + private javax.xml.parsers.DocumentBuilder docBuilder = null; - private org.w3c.dom.Document emotionDocument = null; + private org.w3c.dom.Document emotionDocument = null; - private boolean inputAvailable = false; - private int activation; - private int evaluation; - private int power; - private String text; - private String maryxmlString; - private Locale locale; - - private boolean exitRequested = false; - - - /** Creates new EmoTransformer */ - public EmoTransformer(ProsodyXMLDisplayer emoSpeak) - throws TransformerConfigurationException, ParserConfigurationException - { - this.emoSpeak = emoSpeak; - // Try to find a suitable XSLT transformer - tFactory = javax.xml.transform.TransformerFactory.newInstance(); -/* if (false && tFactory instanceof org.apache.xalan.processor.TransformerFactoryImpl) { - Hashtable xalanEnv = (new org.apache.xalan.xslt.EnvironmentCheck()).getEnvironmentHash(); - String xalan2Version = (String) xalanEnv.get("version.xalan2x"); - if (xalan2Version == null || xalan2Version.equals("")) - xalan2Version = (String) xalanEnv.get("version.xalan2"); - if (xalan2Version != null && !xalan2Version.equals("")) - System.err.println("Using " + xalan2Version); - } else { - */ - System.err.println("Using XSL processor " + tFactory.getClass().getName()); -// } - javax.xml.transform.stream.StreamSource stylesheetStream = - new javax.xml.transform.stream.StreamSource ( - EmoTransformer.class.getResourceAsStream("emotion-to-mary.xsl") - ); - stylesheet = tFactory.newTemplates( stylesheetStream ); - dbFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); - dbFactory.setNamespaceAware(true); - docBuilder = dbFactory.newDocumentBuilder(); - transformer = stylesheet.newTransformer(); + private boolean inputAvailable = false; + private int activation; + private int evaluation; + private int power; + private String text; + private String maryxmlString; + private Locale locale; - } + private boolean exitRequested = false; - /** - * Asynchronously set the latest emotion values. Overwrites any - * previous, unprocessed data. - */ - public synchronized void setEmotionValues(int activation, int evaluation, int power, String text, Locale locale, int r) { - this.activation = activation; - this.evaluation = evaluation; - this.power = power; - this.text = text; - this.locale = locale; - inputAvailable = true; - this.r = r; - notifyAll(); - } - - - public synchronized void requestExit() { - exitRequested = true; - notifyAll(); - } + /** Creates new EmoTransformer */ + public EmoTransformer(ProsodyXMLDisplayer emoSpeak) throws TransformerConfigurationException, ParserConfigurationException { + this.emoSpeak = emoSpeak; + // Try to find a suitable XSLT transformer + tFactory = javax.xml.transform.TransformerFactory.newInstance(); + /* + * if (false && tFactory instanceof org.apache.xalan.processor.TransformerFactoryImpl) { Hashtable xalanEnv = (new + * org.apache.xalan.xslt.EnvironmentCheck()).getEnvironmentHash(); String xalan2Version = (String) + * xalanEnv.get("version.xalan2x"); if (xalan2Version == null || xalan2Version.equals("")) xalan2Version = (String) + * xalanEnv.get("version.xalan2"); if (xalan2Version != null && !xalan2Version.equals("")) System.err.println("Using " + + * xalan2Version); } else { + */ + System.err.println("Using XSL processor " + tFactory.getClass().getName()); + // } + javax.xml.transform.stream.StreamSource stylesheetStream = new javax.xml.transform.stream.StreamSource( + EmoTransformer.class.getResourceAsStream("emotion-to-mary.xsl")); + stylesheet = tFactory.newTemplates(stylesheetStream); + dbFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); + dbFactory.setNamespaceAware(true); + docBuilder = dbFactory.newDocumentBuilder(); + transformer = stylesheet.newTransformer(); - private void createEmotionDocument() { - emotionDocument = docBuilder.getDOMImplementation(). - createDocument(null, "emotion", null); - org.w3c.dom.Element e = emotionDocument.getDocumentElement(); - e.setAttributeNS("http://www.w3.org/XML/1998/namespace", "lang", MaryUtils.locale2xmllang(locale)); - e.setAttribute("activation", String.valueOf(activation)); - e.setAttribute("evaluation", String.valueOf(evaluation)); - e.setAttribute("power", String.valueOf(power)); - e.appendChild(emotionDocument.createTextNode(text)); - } - - private void transformToMaryXML() - throws javax.xml.transform.TransformerException - { - javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource (emotionDocument); - java.io.StringWriter sw = new java.io.StringWriter(); - javax.xml.transform.stream.StreamResult streamResult = new javax.xml.transform.stream.StreamResult (sw); - transformer.transform(domSource, streamResult); - maryxmlString = sw.toString(); - } - - private synchronized void doWait() { - try { - wait(); - } catch (InterruptedException e) {} - } - - public void run() { - while (!exitRequested) { - if (inputAvailable) { - inputAvailable = false; - try { - int r1 = r; - System.err.println("EmoTransformer about to process request no. " + r1); - createEmotionDocument(); - transformToMaryXML(); - System.err.println("EmoTransformer has processed."); - emoSpeak.updateProsodyXML(maryxmlString, r1); - } catch (javax.xml.transform.TransformerException e) { - e.printStackTrace(); - } - } else { - doWait(); - System.err.println("EmoTransformer waking up from wait."); - } - } - System.err.println("EmoTransformer exiting."); - } + } + + /** + * Asynchronously set the latest emotion values. Overwrites any previous, unprocessed data. + */ + public synchronized void setEmotionValues(int activation, int evaluation, int power, String text, Locale locale, int r) { + this.activation = activation; + this.evaluation = evaluation; + this.power = power; + this.text = text; + this.locale = locale; + inputAvailable = true; + this.r = r; + notifyAll(); + } + + public synchronized void requestExit() { + exitRequested = true; + notifyAll(); + } + + private void createEmotionDocument() { + emotionDocument = docBuilder.getDOMImplementation().createDocument(null, "emotion", null); + org.w3c.dom.Element e = emotionDocument.getDocumentElement(); + e.setAttributeNS("http://www.w3.org/XML/1998/namespace", "lang", MaryUtils.locale2xmllang(locale)); + e.setAttribute("activation", String.valueOf(activation)); + e.setAttribute("evaluation", String.valueOf(evaluation)); + e.setAttribute("power", String.valueOf(power)); + e.appendChild(emotionDocument.createTextNode(text)); + } + + private void transformToMaryXML() throws javax.xml.transform.TransformerException { + javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(emotionDocument); + java.io.StringWriter sw = new java.io.StringWriter(); + javax.xml.transform.stream.StreamResult streamResult = new javax.xml.transform.stream.StreamResult(sw); + transformer.transform(domSource, streamResult); + maryxmlString = sw.toString(); + } + + private synchronized void doWait() { + try { + wait(); + } catch (InterruptedException e) { + } + } + + public void run() { + while (!exitRequested) { + if (inputAvailable) { + inputAvailable = false; + try { + int r1 = r; + System.err.println("EmoTransformer about to process request no. " + r1); + createEmotionDocument(); + transformToMaryXML(); + System.err.println("EmoTransformer has processed."); + emoSpeak.updateProsodyXML(maryxmlString, r1); + } catch (javax.xml.transform.TransformerException e) { + e.printStackTrace(); + } + } else { + doWait(); + System.err.println("EmoTransformer waking up from wait."); + } + } + System.err.println("EmoTransformer exiting."); + } } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltraceCircle.java b/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltraceCircle.java index a6404aa0..683d0bb2 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltraceCircle.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltraceCircle.java @@ -20,206 +20,200 @@ package marytts.tools.emospeak; /** - * - * @author schroed + * + * @author schroed */ public class JFeeltraceCircle extends javax.swing.JPanel { - private boolean isCircular = true; // global setting - private int circleSize; + private boolean isCircular = true; // global setting + private int circleSize; - private int cursorDiameter = 30; - public int getCursorDiameter() { return cursorDiameter; } - public void setCursorDiameter(int d) { cursorDiameter = d; } - - private java.awt.geom.RectangularShape feeltraceShape; + private int cursorDiameter = 30; - private TwoDimensionalModel normalizedModel = - new RectangularTwoDimensionalModel(0,0,-100,100,-100,100); + public int getCursorDiameter() { + return cursorDiameter; + } - private java.awt.Dimension requestedSize = new java.awt.Dimension(200, 200); - public void setRequestedSize(java.awt.Dimension requestedSize) - { - this.requestedSize = requestedSize; - } - public java.awt.Dimension getRequestedSize() - { - return requestedSize; - } + public void setCursorDiameter(int d) { + cursorDiameter = d; + } - /** Creates new form JFeeltraceCircle */ - public JFeeltraceCircle(boolean isCircular, - java.awt.Dimension requestedSize) { - this.isCircular = isCircular; - this.requestedSize = requestedSize; - initComponents(); - customInitComponents(); - } - - /** Creates new form JFeeltraceCircle */ - public JFeeltraceCircle() { - initComponents(); - customInitComponents(); - } + private java.awt.geom.RectangularShape feeltraceShape; - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - private void initComponents() {//GEN-BEGIN:initComponents - - setLayout(new java.awt.BorderLayout()); - - addMouseListener(new java.awt.event.MouseAdapter() { - public void mousePressed(java.awt.event.MouseEvent evt) { - formMousePressed(evt); - } - }); - - addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { - public void mouseDragged(java.awt.event.MouseEvent evt) { - formMouseDragged(evt); - } - }); - - }//GEN-END:initComponents + private TwoDimensionalModel normalizedModel = new RectangularTwoDimensionalModel(0, 0, -100, 100, -100, 100); - private void formMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMousePressed - setFeeltraceCursor(evt.getPoint()); - repaint(); - }//GEN-LAST:event_formMousePressed + private java.awt.Dimension requestedSize = new java.awt.Dimension(200, 200); - private void formMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseDragged - setFeeltraceCursor(evt.getPoint()); - repaint(); - }//GEN-LAST:event_formMouseDragged + public void setRequestedSize(java.awt.Dimension requestedSize) { + this.requestedSize = requestedSize; + } - private void customInitComponents() { - if (isCircular) { - feeltraceShape = new java.awt.geom.Ellipse2D.Float(); - } else { // square - feeltraceShape = new java.awt.geom.Rectangle2D.Float(); - } - normalizedModel.addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent e) { - repaint(); - } - }); + public java.awt.Dimension getRequestedSize() { + return requestedSize; + } - } - - protected void paintComponent(java.awt.Graphics graphics) { - super.paintComponent(graphics); - java.awt.Insets insets = getInsets(); - int currentWidth = getWidth() - insets.left - insets.right; - int currentHeight = getHeight() - insets.top - insets.bottom; - int offsetX = insets.left; - int offsetY = insets.top; - if (currentWidth >= currentHeight) { - circleSize = currentHeight; - offsetX += (currentWidth - circleSize) / 2; - } else { - circleSize = currentWidth; - offsetY += (currentHeight - circleSize) / 2; - } - if (isCircular) { - graphics.setColor(java.awt.Color.white); - graphics.fillOval(offsetX,offsetY,circleSize,circleSize); - graphics.setColor(java.awt.Color.black); - graphics.drawOval(offsetX,offsetY,circleSize,circleSize); - graphics.drawLine(offsetX,offsetY+circleSize/2, - offsetX+circleSize,offsetY+circleSize/2); - graphics.drawLine(offsetX+circleSize/2,offsetY, - offsetX+circleSize/2,offsetY+circleSize); - } else { // square - graphics.setColor(java.awt.Color.white); - graphics.fillRect(offsetX,offsetY,circleSize,circleSize); - graphics.setColor(java.awt.Color.black); - graphics.drawRect(offsetX,offsetY,circleSize,circleSize); - graphics.drawLine(offsetX,offsetY+circleSize/2, - offsetX+circleSize,offsetY+circleSize/2); - graphics.drawLine(offsetX+circleSize/2,offsetY, - offsetX+circleSize/2,offsetY+circleSize); - } - feeltraceShape.setFrame(offsetX, offsetY, circleSize, circleSize); - - // And now the cursor - int x = (int) (feeltraceShape.getCenterX() + - normalizedModel.getX() * - (feeltraceShape.getMaxX() - feeltraceShape.getCenterX()) / - normalizedModel.getMaxX()); - int y = (int) (feeltraceShape.getCenterY() - - normalizedModel.getY() * - (feeltraceShape.getMaxY() - feeltraceShape.getCenterY()) / - normalizedModel.getMaxY()); - graphics.setColor(java.awt.Color.green); - graphics.fillOval(x - cursorDiameter/2, y - cursorDiameter/2, - cursorDiameter, cursorDiameter); - - } + /** Creates new form JFeeltraceCircle */ + public JFeeltraceCircle(boolean isCircular, java.awt.Dimension requestedSize) { + this.isCircular = isCircular; + this.requestedSize = requestedSize; + initComponents(); + customInitComponents(); + } - /** - * Define the location of the cursor; - * the actual drawing is done in paintComponents(). - */ - private void setFeeltraceCursor(java.awt.Point p) { - java.awt.Point newLocation; - if (feeltraceShape.contains(p)) { - newLocation = p; - } else { - if (isCircular) { - double px = p.getX() - feeltraceShape.getCenterX(); - double py = p.getY() - feeltraceShape.getCenterY(); - // Determine angle, paint cursor at extreme possible - // value at that angle - if (py == 0) { - newLocation = new java.awt.Point((int)feeltraceShape.getCenterX() + circleSize, - (int)feeltraceShape.getCenterY()); - } else { - // these formulae follow from a little drawing: - double y = (circleSize/2) /Math.sqrt(1 + px*px/(py*py)); - if (py < 0) y = -y; - double x = px/py * y; - newLocation = new java.awt.Point((int) (feeltraceShape.getCenterX() + x), - (int) (feeltraceShape.getCenterY() + y)); - } - } else { - // ignore out-of-bounds for rectangle - return; - } - } - // In the Y normalisation, add a - sign, because top=+100, bottom=-100 - normalizedModel.setXY((int)((newLocation.getX() - feeltraceShape.getCenterX()) / - (feeltraceShape.getMaxX() - feeltraceShape.getCenterX()) * normalizedModel.getMaxX()), - -(int)((newLocation.getY() - feeltraceShape.getCenterY()) / - (feeltraceShape.getMaxY() - feeltraceShape.getCenterY()) * normalizedModel.getMaxY())); + /** Creates new form JFeeltraceCircle */ + public JFeeltraceCircle() { + initComponents(); + customInitComponents(); + } - } - - public void setNormalizedLocation(int x, int y) { - normalizedModel.setXY(x,y); - } - - public void setNormalizedX(int x) { - normalizedModel.setX(x); - } - - public void setNormalizedY(int y) { - normalizedModel.setY(y); - } + /** + * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of + * this method is always regenerated by the Form Editor. + */ + private void initComponents() {// GEN-BEGIN:initComponents - public int getNormalizedX() { - return normalizedModel.getX(); - } - - public int getNormalizedY() { - return normalizedModel.getY(); - } + setLayout(new java.awt.BorderLayout()); - public TwoDimensionalModel getNormalizedModel() { - return normalizedModel; - } + addMouseListener(new java.awt.event.MouseAdapter() { + public void mousePressed(java.awt.event.MouseEvent evt) { + formMousePressed(evt); + } + }); + + addMouseMotionListener(new java.awt.event.MouseMotionAdapter() { + public void mouseDragged(java.awt.event.MouseEvent evt) { + formMouseDragged(evt); + } + }); + + }// GEN-END:initComponents + + private void formMousePressed(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_formMousePressed + setFeeltraceCursor(evt.getPoint()); + repaint(); + }// GEN-LAST:event_formMousePressed + + private void formMouseDragged(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_formMouseDragged + setFeeltraceCursor(evt.getPoint()); + repaint(); + }// GEN-LAST:event_formMouseDragged + + private void customInitComponents() { + if (isCircular) { + feeltraceShape = new java.awt.geom.Ellipse2D.Float(); + } else { // square + feeltraceShape = new java.awt.geom.Rectangle2D.Float(); + } + normalizedModel.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent e) { + repaint(); + } + }); + + } + + protected void paintComponent(java.awt.Graphics graphics) { + super.paintComponent(graphics); + java.awt.Insets insets = getInsets(); + int currentWidth = getWidth() - insets.left - insets.right; + int currentHeight = getHeight() - insets.top - insets.bottom; + int offsetX = insets.left; + int offsetY = insets.top; + if (currentWidth >= currentHeight) { + circleSize = currentHeight; + offsetX += (currentWidth - circleSize) / 2; + } else { + circleSize = currentWidth; + offsetY += (currentHeight - circleSize) / 2; + } + if (isCircular) { + graphics.setColor(java.awt.Color.white); + graphics.fillOval(offsetX, offsetY, circleSize, circleSize); + graphics.setColor(java.awt.Color.black); + graphics.drawOval(offsetX, offsetY, circleSize, circleSize); + graphics.drawLine(offsetX, offsetY + circleSize / 2, offsetX + circleSize, offsetY + circleSize / 2); + graphics.drawLine(offsetX + circleSize / 2, offsetY, offsetX + circleSize / 2, offsetY + circleSize); + } else { // square + graphics.setColor(java.awt.Color.white); + graphics.fillRect(offsetX, offsetY, circleSize, circleSize); + graphics.setColor(java.awt.Color.black); + graphics.drawRect(offsetX, offsetY, circleSize, circleSize); + graphics.drawLine(offsetX, offsetY + circleSize / 2, offsetX + circleSize, offsetY + circleSize / 2); + graphics.drawLine(offsetX + circleSize / 2, offsetY, offsetX + circleSize / 2, offsetY + circleSize); + } + feeltraceShape.setFrame(offsetX, offsetY, circleSize, circleSize); + + // And now the cursor + int x = (int) (feeltraceShape.getCenterX() + normalizedModel.getX() + * (feeltraceShape.getMaxX() - feeltraceShape.getCenterX()) / normalizedModel.getMaxX()); + int y = (int) (feeltraceShape.getCenterY() - normalizedModel.getY() + * (feeltraceShape.getMaxY() - feeltraceShape.getCenterY()) / normalizedModel.getMaxY()); + graphics.setColor(java.awt.Color.green); + graphics.fillOval(x - cursorDiameter / 2, y - cursorDiameter / 2, cursorDiameter, cursorDiameter); + + } + + /** + * Define the location of the cursor; the actual drawing is done in paintComponents(). + */ + private void setFeeltraceCursor(java.awt.Point p) { + java.awt.Point newLocation; + if (feeltraceShape.contains(p)) { + newLocation = p; + } else { + if (isCircular) { + double px = p.getX() - feeltraceShape.getCenterX(); + double py = p.getY() - feeltraceShape.getCenterY(); + // Determine angle, paint cursor at extreme possible + // value at that angle + if (py == 0) { + newLocation = new java.awt.Point((int) feeltraceShape.getCenterX() + circleSize, + (int) feeltraceShape.getCenterY()); + } else { + // these formulae follow from a little drawing: + double y = (circleSize / 2) / Math.sqrt(1 + px * px / (py * py)); + if (py < 0) + y = -y; + double x = px / py * y; + newLocation = new java.awt.Point((int) (feeltraceShape.getCenterX() + x), + (int) (feeltraceShape.getCenterY() + y)); + } + } else { + // ignore out-of-bounds for rectangle + return; + } + } + // In the Y normalisation, add a - sign, because top=+100, bottom=-100 + normalizedModel.setXY( + (int) ((newLocation.getX() - feeltraceShape.getCenterX()) + / (feeltraceShape.getMaxX() - feeltraceShape.getCenterX()) * normalizedModel.getMaxX()), + -(int) ((newLocation.getY() - feeltraceShape.getCenterY()) + / (feeltraceShape.getMaxY() - feeltraceShape.getCenterY()) * normalizedModel.getMaxY())); + + } + + public void setNormalizedLocation(int x, int y) { + normalizedModel.setXY(x, y); + } + + public void setNormalizedX(int x) { + normalizedModel.setX(x); + } + + public void setNormalizedY(int y) { + normalizedModel.setY(y); + } + + public int getNormalizedX() { + return normalizedModel.getX(); + } + + public int getNormalizedY() { + return normalizedModel.getY(); + } + + public TwoDimensionalModel getNormalizedModel() { + return normalizedModel; + } } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltracePanel.java b/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltracePanel.java index 7a9c0ac3..862575bf 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltracePanel.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/JFeeltracePanel.java @@ -18,192 +18,191 @@ * */ package marytts.tools.emospeak; + import java.awt.Graphics; import javax.swing.BoundedRangeModel; import javax.swing.JPanel; /** - * - * @author Marc Schröder + * + * @author Marc Schröder */ public class JFeeltracePanel extends JPanel { - - private boolean showPower = true; - public boolean showPower() { - return showPower; - } - - public void setShowPower(boolean showPower) - { - this.showPower = showPower; - } - public TwoDimensionalModel feeltraceModel() { - return jFeeltraceCircle1.getNormalizedModel(); - } - - private BoundedRangeModel powerModel = - new javax.swing.DefaultBoundedRangeModel(0,0,-100,100); - public BoundedRangeModel powerModel() { - return powerModel; - } - - /** Creates new form JFeeltracePanel */ - public JFeeltracePanel(boolean showPower) { - this.showPower = showPower; - initComponents(); - customInitComponents(); - } - - /** Creates new form JFeeltracePanel */ - public JFeeltracePanel() { - initComponents(); - customInitComponents(); - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - private void initComponents() {//GEN-BEGIN:initComponents - java.awt.GridBagConstraints gridBagConstraints; + private boolean showPower = true; - slPower = new javax.swing.JSlider(); - lMaxPower = new javax.swing.JLabel(); - lMinPower = new javax.swing.JLabel(); - lMaxActivation = new javax.swing.JLabel(); - lMinEvaluation = new javax.swing.JLabel(); - lMaxEvaluation = new javax.swing.JLabel(); - lMinActivation = new javax.swing.JLabel(); - jFeeltraceCircle1 = new JFeeltraceCircle(); + public boolean showPower() { + return showPower; + } - setLayout(new java.awt.GridBagLayout()); + public void setShowPower(boolean showPower) { + this.showPower = showPower; + } - setPreferredSize(new java.awt.Dimension(500, 350)); - slPower.setMinimum(-100); - slPower.setOrientation(javax.swing.JSlider.VERTICAL); - slPower.setValue(0); - slPower.addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent evt) { - slPowerStateChanged(evt); - } - }); + public TwoDimensionalModel feeltraceModel() { + return jFeeltraceCircle1.getNormalizedModel(); + } - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 1; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - add(slPower, gridBagConstraints); + private BoundedRangeModel powerModel = new javax.swing.DefaultBoundedRangeModel(0, 0, -100, 100); - lMaxPower.setText("very dominant"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 0; - add(lMaxPower, gridBagConstraints); + public BoundedRangeModel powerModel() { + return powerModel; + } - lMinPower.setText("very submissive"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 5; - gridBagConstraints.gridy = 2; - add(lMinPower, gridBagConstraints); + /** Creates new form JFeeltracePanel */ + public JFeeltracePanel(boolean showPower) { + this.showPower = showPower; + initComponents(); + customInitComponents(); + } - lMaxActivation.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - lMaxActivation.setText("very active"); - lMaxActivation.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM); - lMaxActivation.setAlignmentX(0.5F); - lMaxActivation.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 0; - gridBagConstraints.gridwidth = 3; - gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; - gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; - add(lMaxActivation, gridBagConstraints); + /** Creates new form JFeeltracePanel */ + public JFeeltracePanel() { + initComponents(); + customInitComponents(); + } - lMinEvaluation.setText("very
negative"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 0; - gridBagConstraints.gridy = 1; - add(lMinEvaluation, gridBagConstraints); + /** + * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of + * this method is always regenerated by the Form Editor. + */ + private void initComponents() {// GEN-BEGIN:initComponents + java.awt.GridBagConstraints gridBagConstraints; - lMaxEvaluation.setText("very
positive"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 4; - gridBagConstraints.gridy = 1; - add(lMaxEvaluation, gridBagConstraints); + slPower = new javax.swing.JSlider(); + lMaxPower = new javax.swing.JLabel(); + lMinPower = new javax.swing.JLabel(); + lMaxActivation = new javax.swing.JLabel(); + lMinEvaluation = new javax.swing.JLabel(); + lMaxEvaluation = new javax.swing.JLabel(); + lMinActivation = new javax.swing.JLabel(); + jFeeltraceCircle1 = new JFeeltraceCircle(); - lMinActivation.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); - lMinActivation.setText("very passive"); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 2; - gridBagConstraints.gridwidth = 3; - gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; - add(lMinActivation, gridBagConstraints); + setLayout(new java.awt.GridBagLayout()); - jFeeltraceCircle1.setFont(new java.awt.Font("Dialog", 0, 11)); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.gridx = 1; - gridBagConstraints.gridy = 1; - gridBagConstraints.gridwidth = 3; - gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; - gridBagConstraints.weightx = 0.1; - gridBagConstraints.weighty = 0.1; - gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10); - add(jFeeltraceCircle1, gridBagConstraints); + setPreferredSize(new java.awt.Dimension(500, 350)); + slPower.setMinimum(-100); + slPower.setOrientation(javax.swing.JSlider.VERTICAL); + slPower.setValue(0); + slPower.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + slPowerStateChanged(evt); + } + }); - }//GEN-END:initComponents - - - private void slPowerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_slPowerStateChanged - powerModel.setValue(slPower.getValue()); - }//GEN-LAST:event_slPowerStateChanged - - private void customInitComponents() { - verifyPowerVisible(); - feeltraceModel().addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent e) { - updateFeeltraceDisplays(); - } - }); - if (showPower) { - powerModel.addChangeListener(new javax.swing.event.ChangeListener() { - public void stateChanged(javax.swing.event.ChangeEvent e) { - updatePowerDisplays(); - } - }); - } - } - - protected void paintComponent(Graphics graphics) { - verifyPowerVisible(); - super.paintComponent(graphics); - } - - public void verifyPowerVisible() { - lMaxPower.setVisible(showPower); - lMinPower.setVisible(showPower); - slPower.setVisible(showPower); - } - - private void updateFeeltraceDisplays() { - } + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 1; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + add(slPower, gridBagConstraints); + + lMaxPower.setText("very dominant"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 0; + add(lMaxPower, gridBagConstraints); + + lMinPower.setText("very submissive"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 5; + gridBagConstraints.gridy = 2; + add(lMinPower, gridBagConstraints); + + lMaxActivation.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lMaxActivation.setText("very active"); + lMaxActivation.setVerticalAlignment(javax.swing.SwingConstants.BOTTOM); + lMaxActivation.setAlignmentX(0.5F); + lMaxActivation.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 0; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL; + gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; + add(lMaxActivation, gridBagConstraints); + + lMinEvaluation.setText("very
negative"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 0; + gridBagConstraints.gridy = 1; + add(lMinEvaluation, gridBagConstraints); + + lMaxEvaluation.setText("very
positive"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 4; + gridBagConstraints.gridy = 1; + add(lMaxEvaluation, gridBagConstraints); + + lMinActivation.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + lMinActivation.setText("very passive"); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 2; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; + add(lMinActivation, gridBagConstraints); + + jFeeltraceCircle1.setFont(new java.awt.Font("Dialog", 0, 11)); + gridBagConstraints = new java.awt.GridBagConstraints(); + gridBagConstraints.gridx = 1; + gridBagConstraints.gridy = 1; + gridBagConstraints.gridwidth = 3; + gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints.weightx = 0.1; + gridBagConstraints.weighty = 0.1; + gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10); + add(jFeeltraceCircle1, gridBagConstraints); + + }// GEN-END:initComponents + + private void slPowerStateChanged(javax.swing.event.ChangeEvent evt) {// GEN-FIRST:event_slPowerStateChanged + powerModel.setValue(slPower.getValue()); + }// GEN-LAST:event_slPowerStateChanged + + private void customInitComponents() { + verifyPowerVisible(); + feeltraceModel().addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent e) { + updateFeeltraceDisplays(); + } + }); + if (showPower) { + powerModel.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent e) { + updatePowerDisplays(); + } + }); + } + } + + protected void paintComponent(Graphics graphics) { + verifyPowerVisible(); + super.paintComponent(graphics); + } + + public void verifyPowerVisible() { + lMaxPower.setVisible(showPower); + lMinPower.setVisible(showPower); + slPower.setVisible(showPower); + } + + private void updateFeeltraceDisplays() { + } + + private void updatePowerDisplays() { + slPower.setValue(powerModel.getValue()); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel lMinActivation; + private javax.swing.JLabel lMaxEvaluation; + private javax.swing.JSlider slPower; + private javax.swing.JLabel lMinEvaluation; + private javax.swing.JLabel lMinPower; + private javax.swing.JLabel lMaxActivation; + private javax.swing.JLabel lMaxPower; + private JFeeltraceCircle jFeeltraceCircle1; + // End of variables declaration//GEN-END:variables - private void updatePowerDisplays() { - slPower.setValue(powerModel.getValue()); - } - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel lMinActivation; - private javax.swing.JLabel lMaxEvaluation; - private javax.swing.JSlider slPower; - private javax.swing.JLabel lMinEvaluation; - private javax.swing.JLabel lMinPower; - private javax.swing.JLabel lMaxActivation; - private javax.swing.JLabel lMaxPower; - private JFeeltraceCircle jFeeltraceCircle1; - // End of variables declaration//GEN-END:variables - } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/ProsodyXMLDisplayer.java b/marytts-client/src/main/java/marytts/tools/emospeak/ProsodyXMLDisplayer.java index 03225b99..b7f302ee 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/ProsodyXMLDisplayer.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/ProsodyXMLDisplayer.java @@ -20,12 +20,11 @@ package marytts.tools.emospeak; /** - * - * @author schroed + * + * @author schroed */ public interface ProsodyXMLDisplayer { - - void updateProsodyXML(String prosodyxmlString, int r1); - -} + void updateProsodyXML(String prosodyxmlString, int r1); + +} diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/RectangularTwoDimensionalModel.java b/marytts-client/src/main/java/marytts/tools/emospeak/RectangularTwoDimensionalModel.java index dcb0c8ec..454727de 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/RectangularTwoDimensionalModel.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/RectangularTwoDimensionalModel.java @@ -20,115 +20,130 @@ package marytts.tools.emospeak; /** - * - * @author Marc Schröder + * + * @author Marc Schröder */ public class RectangularTwoDimensionalModel implements TwoDimensionalModel { - private int x; - private int y; - private int minX; - private int maxX; - private int minY; - private int maxY; - private java.util.List changeListeners = new java.util.ArrayList(); - - /** Creates new RectangularTwoDimensionalModel, with all values - * set to 0. */ - public RectangularTwoDimensionalModel() { - this(0,0,0,0,0,0); - } + private int x; + private int y; + private int minX; + private int maxX; + private int minY; + private int maxY; + private java.util.List changeListeners = new java.util.ArrayList(); - /** Creates new RectangularTwoDimensionalModel */ - public RectangularTwoDimensionalModel(int x, int y, int minX, int maxX, int minY, int maxY) { - this.x = x; - this.y = y; - this.minX = minX; - this.maxX = maxX; - this.minY = minY; - this.maxY = maxY; - } + /** + * Creates new RectangularTwoDimensionalModel, with all values set to 0. + */ + public RectangularTwoDimensionalModel() { + this(0, 0, 0, 0, 0, 0); + } - /** Adds a ChangeListener to the model's listener list. */ - public void addChangeListener(javax.swing.event.ChangeListener l) { - if (!changeListeners.contains(l)) - changeListeners.add(l); - } - - /** Removes a ChangeListener from the model's listener list. */ - public void removeChangeListener(javax.swing.event.ChangeListener l) { - changeListeners.remove(l); - } + /** Creates new RectangularTwoDimensionalModel */ + public RectangularTwoDimensionalModel(int x, int y, int minX, int maxX, int minY, int maxY) { + this.x = x; + this.y = y; + this.minX = minX; + this.maxX = maxX; + this.minY = minY; + this.maxY = maxY; + } - private void notifyChangeListeners() { - java.util.Iterator it = changeListeners.iterator(); - javax.swing.event.ChangeEvent e = new javax.swing.event.ChangeEvent(this); - while (it.hasNext()) { - javax.swing.event.ChangeListener l = (javax.swing.event.ChangeListener) it.next(); - l.stateChanged(e); - } - } - - /** Set the Maximum X value. */ - public void setMaxX(int maxX) { - this.maxX = maxX; - } - - /** Set the Maximum Y value. */ - public void setMaxY(int maxY) { - this.maxY = maxY; - } - - /** Set the Minimum X value. */ - public void setMinX(int minX) { - this.minX = minX; - } - - /** Set the Minimum Y value. */ - public void setMinY(int minY) { - this.minY = minY; - } - - /** Set X value. - * If beyond the Max and Min range, value is ignored. - */ - public void setX(int x) { - if (minX <= x && x <= maxX) { - this.x = x; - notifyChangeListeners(); - } - } - - /** Jointly set x and y values. - * If one of the values is beyond the - * respective Max and Min range, both values are ignored. - */ - public void setXY(int x, int y) { - if (minX <= x && x <= maxX && - minY <= y && y <= maxY) { - this.x = x; - this.y = y; - notifyChangeListeners(); - } - } - - /** Set Y value. - * If beyond the Max and Min range, value is ignored. - */ - public void setY(int y) { - if (minY <= y && y <= maxY) { - this.y = y; - notifyChangeListeners(); - } - } - - /** Get the X value. */ - public int getX() { return x; } - /** Get the Y value. */ - public int getY() { return y; } - public int getMaxX() { return maxX; } - public int getMinX() { return minX; } - public int getMaxY() { return maxY; } - public int getMinY() { return minY; } + /** Adds a ChangeListener to the model's listener list. */ + public void addChangeListener(javax.swing.event.ChangeListener l) { + if (!changeListeners.contains(l)) + changeListeners.add(l); + } + + /** Removes a ChangeListener from the model's listener list. */ + public void removeChangeListener(javax.swing.event.ChangeListener l) { + changeListeners.remove(l); + } + + private void notifyChangeListeners() { + java.util.Iterator it = changeListeners.iterator(); + javax.swing.event.ChangeEvent e = new javax.swing.event.ChangeEvent(this); + while (it.hasNext()) { + javax.swing.event.ChangeListener l = (javax.swing.event.ChangeListener) it.next(); + l.stateChanged(e); + } + } + + /** Set the Maximum X value. */ + public void setMaxX(int maxX) { + this.maxX = maxX; + } + + /** Set the Maximum Y value. */ + public void setMaxY(int maxY) { + this.maxY = maxY; + } + + /** Set the Minimum X value. */ + public void setMinX(int minX) { + this.minX = minX; + } + + /** Set the Minimum Y value. */ + public void setMinY(int minY) { + this.minY = minY; + } + + /** + * Set X value. If beyond the Max and Min range, value is ignored. + */ + public void setX(int x) { + if (minX <= x && x <= maxX) { + this.x = x; + notifyChangeListeners(); + } + } + + /** + * Jointly set x and y values. If one of the values is beyond the respective Max and Min range, both values are ignored. + */ + public void setXY(int x, int y) { + if (minX <= x && x <= maxX && minY <= y && y <= maxY) { + this.x = x; + this.y = y; + notifyChangeListeners(); + } + } + + /** + * Set Y value. If beyond the Max and Min range, value is ignored. + */ + public void setY(int y) { + if (minY <= y && y <= maxY) { + this.y = y; + notifyChangeListeners(); + } + } + + /** Get the X value. */ + public int getX() { + return x; + } + + /** Get the Y value. */ + public int getY() { + return y; + } + + public int getMaxX() { + return maxX; + } + + public int getMinX() { + return minX; + } + + public int getMaxY() { + return maxY; + } + + public int getMinY() { + return minY; + } } - diff --git a/marytts-client/src/main/java/marytts/tools/emospeak/TwoDimensionalModel.java b/marytts-client/src/main/java/marytts/tools/emospeak/TwoDimensionalModel.java index da1597da..ecbce821 100644 --- a/marytts-client/src/main/java/marytts/tools/emospeak/TwoDimensionalModel.java +++ b/marytts-client/src/main/java/marytts/tools/emospeak/TwoDimensionalModel.java @@ -20,45 +20,54 @@ package marytts.tools.emospeak; /** - * - * @author Marc Schröder + * + * @author Marc Schröder */ public interface TwoDimensionalModel { - /** Jointly set x and y values. - * If one of the values is beyond the - * respective Max and Min range, both values are ignored. - */ - public void setXY(int x, int y); - /** Set X value. - * If beyond the Max and Min range, value is ignored. - */ - public void setX(int x); - /** Set Y value. - * If beyond the Max and Min range, value is ignored. - */ - public void setY(int y); - /** Set the Maximum X value. */ - public void setMaxX(int maxX); - /** Set the Minimum X value. */ - public void setMinX(int minX); - /** Set the Maximum Y value. */ - public void setMaxY(int maxY); - /** Set the Minimum Y value. */ - public void setMinY(int minY); - - /** Get the X value. */ - public int getX(); - /** Get the Y value. */ - public int getY(); - public int getMaxX(); - public int getMinX(); - public int getMaxY(); - public int getMinY(); - - /** Adds a ChangeListener to the model's listener list. */ - public void addChangeListener(javax.swing.event.ChangeListener l); - /** Removes a ChangeListener from the model's listener list. */ - public void removeChangeListener(javax.swing.event.ChangeListener l); + /** + * Jointly set x and y values. If one of the values is beyond the respective Max and Min range, both values are ignored. + */ + public void setXY(int x, int y); + + /** + * Set X value. If beyond the Max and Min range, value is ignored. + */ + public void setX(int x); + + /** + * Set Y value. If beyond the Max and Min range, value is ignored. + */ + public void setY(int y); + + /** Set the Maximum X value. */ + public void setMaxX(int maxX); + + /** Set the Minimum X value. */ + public void setMinX(int minX); + + /** Set the Maximum Y value. */ + public void setMaxY(int maxY); + + /** Set the Minimum Y value. */ + public void setMinY(int minY); + + /** Get the X value. */ + public int getX(); + + /** Get the Y value. */ + public int getY(); + + public int getMaxX(); + + public int getMinX(); + + public int getMaxY(); + + public int getMinY(); + + /** Adds a ChangeListener to the model's listener list. */ + public void addChangeListener(javax.swing.event.ChangeListener l); + + /** Removes a ChangeListener from the model's listener list. */ + public void removeChangeListener(javax.swing.event.ChangeListener l); } - -