All Downloads are FREE. Search and download functionalities are using the official Maven repository.

marytts.tools.voiceimport.DatabaseImportMain Maven / Gradle / Ivy

The newest version!
/**
 * Portions Copyright 2006 DFKI GmbH.
 * Portions Copyright 2001 Sun Microsystems, Inc.
 * Portions Copyright 1999-2001 Language Technologies Institute, 
 * Carnegie Mellon University.
 * 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.
 */
package marytts.tools.voiceimport;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;

import org.apache.commons.io.FileUtils;

import marytts.util.io.BasenameList;

/**
 * The single purpose of the DatabaseImportMain class is to provide a main which executes the sequence of database import and
 * conversion operations.
 * 
 * @author sacha, anna
 * 
 */
public class DatabaseImportMain extends JFrame {
	protected VoiceImportComponent[] components;
	protected String[][] groups2Comps;
	protected JCheckBox[] checkboxes;
	protected JButton runButton;
	protected DatabaseLayout db = null;
	protected BasenameList bnl = null;
	protected String currentComponent;

	public DatabaseImportMain(String title, VoiceImportComponent[] components, DatabaseLayout db, String[][] groups2Comps) {
		super(title);
		this.components = components;
		this.checkboxes = new JCheckBox[components.length];
		this.db = db;
		this.bnl = db.getBasenames();
		this.groups2Comps = groups2Comps;
		currentComponent = "global properties";
		setupGUI();
	}

	protected void setupGUI() {
		// A scroll pane containing one labelled checkbox per component,
		// and a "run selected components" button below.
		GridBagLayout gridBagLayout = new GridBagLayout();
		GridBagConstraints gridC = new GridBagConstraints();
		getContentPane().setLayout(gridBagLayout);

		JPanel checkboxPane = new JPanel();
		checkboxPane.setLayout(new BoxLayout(checkboxPane, BoxLayout.Y_AXIS));
		// checkboxPane.setPreferredSize(new Dimension(300, 300));
		int compIndex = 0;
		for (int j = 0; j < groups2Comps.length; j++) {
			String[] nextGroup = groups2Comps[j];
			JPanel groupPane = new JPanel();
			groupPane.setLayout(new BoxLayout(groupPane, BoxLayout.Y_AXIS));
			groupPane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(nextGroup[0]),
					BorderFactory.createEmptyBorder(1, 1, 1, 1)));
			for (int i = 1; i < nextGroup.length; i++) {
				JButton configButton = new JButton();
				Icon configIcon = new ImageIcon(DatabaseImportMain.class.getResource("configure.png"), "Configure");
				configButton.setIcon(configIcon);
				configButton.setPreferredSize(new Dimension(configIcon.getIconWidth(), configIcon.getIconHeight()));
				configButton.addActionListener(new ConfigButtonActionListener(nextGroup[i]));
				configButton.setBorderPainted(false);
				// System.out.println("Adding checkbox for "+components[i].getClass().getName());
				checkboxes[compIndex] = new JCheckBox(nextGroup[i]);
				checkboxes[compIndex].setFocusable(true);
				// checkboxes[i].setPreferredSize(new Dimension(200, 30));
				JPanel line = new JPanel();
				line.setLayout(new BorderLayout(5, 0));
				line.add(configButton, BorderLayout.WEST);
				line.add(checkboxes[compIndex], BorderLayout.CENTER);
				groupPane.add(line);
				compIndex++;
			}
			checkboxPane.add(groupPane);
		}
		gridC.gridx = 0;
		gridC.gridy = 0;
		gridC.fill = GridBagConstraints.BOTH;
		JScrollPane scrollPane = new JScrollPane(checkboxPane);
		scrollPane.setPreferredSize(new Dimension(450, 300));
		gridBagLayout.setConstraints(scrollPane, gridC);
		getContentPane().add(scrollPane);

		JButton helpButton = new JButton("Help");
		helpButton.setMnemonic(KeyEvent.VK_H);
		helpButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				displayHelpGUI();
			}
		});
		JButton settingsButton = new JButton("Settings");
		settingsButton.setMnemonic(KeyEvent.VK_S);
		settingsButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				currentComponent = "Global properties";
				displaySettingsGUI();
			}
		});
		runButton = new JButton("Run");
		runButton.setMnemonic(KeyEvent.VK_R);
		runButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				runSelectedComponents();
			}
		});

		JButton quitAndSaveButton = new JButton("Quit");
		quitAndSaveButton.setMnemonic(KeyEvent.VK_Q);
		quitAndSaveButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				try {
					askIfSave();
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
				System.exit(0);
			}
		});

		gridC.gridy = 1;
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new FlowLayout());
		// buttonPanel.setLayout(new BoxLayout(buttonPanel,BoxLayout.X_AXIS));
		// runButton.setAlignmentX(JButton.LEFT_ALIGNMENT);
		buttonPanel.add(runButton);
		// helpButton.setAlignmentX(JButton.LEFT_ALIGNMENT);
		buttonPanel.add(helpButton);
		// settingsButton.setAlignmentX(JButton.LEFT_ALIGNMENT);
		buttonPanel.add(settingsButton);
		// buttonPanel.add(Box.createHorizontalGlue());
		// quitAndSaveButton.setAlignmentX(JButton.RIGHT_ALIGNMENT);
		buttonPanel.add(quitAndSaveButton);
		gridBagLayout.setConstraints(buttonPanel, gridC);
		getContentPane().add(buttonPanel);

		// getContentPane().setPreferredSize(new Dimension(300, 300));
		// End program when closing window:
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent evt) {
				try {
					askIfSave();
				} catch (IOException ioe) {
					ioe.printStackTrace();
				}
				System.exit(0);
			}
		});
	}

	protected void displayHelpGUI() {
		Thread helpGUIThread = new Thread("DisplayHelpGUIThread") {
			public void run() {
				boolean ok = new HelpGUI(DatabaseImportMain.class.getResourceAsStream("help_import_main.html")).display();
				if (!ok) {
					System.out.println("Error displaying helpfile " + "help_import_main.html");
				}
			}
		};
		helpGUIThread.start();
	}

	protected void displaySettingsGUI() {
		new Thread("DisplaySettingsGUIThread") {
			public void run() {
				Map comps2HelpText = db.getComps2HelpText();
				new SettingsGUI(db, db.getAllPropsForDisplay(), currentComponent, comps2HelpText);
			}
		}.start();
	}

	/**
	 * Run the selected components in a different thread.
	 * 
	 */
	protected void runSelectedComponents() {
		new Thread("RunSelectedComponentsThread") {
			public void run() {
				try {
					runButton.setEnabled(false);
					for (int i = 0; i < components.length; i++) {
						if (checkboxes[i].isSelected()) {
							boolean success = false;
							Container parent = checkboxes[i].getParent();
							final JProgressBar progress = new JProgressBar();
							final VoiceImportComponent oneComponent = components[i];
							if (oneComponent.getProgress() != -1) {
								progress.setStringPainted(true);
								new Thread("ProgressThread") {
									public void run() {
										int percent = 0;
										while (progress.isVisible()) {
											progress.setValue(percent);
											try {
												Thread.sleep(500);
											} catch (InterruptedException ie) {
											}
											percent = oneComponent.getProgress();
										}
									}
								}.start();
							} else {
								progress.setIndeterminate(true);
							}
							parent.add(progress, BorderLayout.EAST);
							progress.setVisible(true);
							parent.validate();
							try {
								success = oneComponent.compute();
							} catch (Exception exc) {
								checkboxes[i].setBackground(Color.RED);
								throw new Exception("The component " + checkboxes[i].getText()
										+ " produced the following exception: ", exc);
							} finally {
								checkboxes[i].setSelected(false);
								progress.setVisible(false);
							}
							if (success) {
								checkboxes[i].setBackground(Color.GREEN);
							} else {
								checkboxes[i].setBackground(Color.RED);
							}
						}
					}
				} catch (Throwable e) {
					e.printStackTrace();
				} finally {
					runButton.setEnabled(true);
				}

			}
		}.start();
	}

	protected void askIfSave() throws IOException {
		if (bnl.hasChanged()) {
			int answer = JOptionPane.showOptionDialog(this, "Do you want to save the list of basenames?", "Save?",
					JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
			if (answer == JOptionPane.YES_OPTION) {
				JFileChooser fc = new JFileChooser();
				fc.setSelectedFile(new File(db.getProp(db.BASENAMEFILE)));
				int returnVal = fc.showSaveDialog(this);
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					bnl.write(fc.getSelectedFile());
				}
			}
		} else {
			System.exit(0);
		}
	}

	protected void closeGUI() {
		// This doesn't work because Java cannot close the X11 connection, see
		// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4420885
		int answer = JOptionPane.showOptionDialog(this, "Do you want to close this GUI?\n\n"
				+ "The components that are currently running will continue to run,\n"
				+ "but you will not be able to save settings or select/deselect\n" + "components to run.\n"
				+ "This may be useful when running this tool using 'nohup' on a server\n"
				+ "because it allows you to log off without stopping the process.", "Really close GUI?",
				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
		if (answer == JOptionPane.YES_OPTION) {
			this.setVisible(false);
			this.dispose();
		}
	}

	public static String[][] readComponentList(InputStream fileIn) throws IOException {
		List groups = new ArrayList();
		Map groups2Names = new HashMap();
		Map> groups2Components = new HashMap>();
		try {
			BufferedReader in = new BufferedReader(new InputStreamReader(fileIn, "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				line = line.trim();
				if (line.startsWith("#") || line.equals(""))
					continue;
				// System.out.println(line);
				String[] lineSplit = line.split(" ");
				if (lineSplit[0].equals("group")) {
					// we have a group
					// line looks like "group basic_data basic data files"
					groups.add(lineSplit[1]);
					StringBuilder nameBuf = new StringBuilder();
					for (int i = 2; i < lineSplit.length; i++) {
						nameBuf.append(lineSplit[i] + " ");
					}
					groups2Names.put(lineSplit[1], nameBuf.toString().trim());
				} else {
					// we have a component
					// line looks like
					// "marytts.tools.voiceimport.WaveformTimelineMaker basic_data"
					if (groups2Components.containsKey(lineSplit[1])) {
						List comps = groups2Components.get(lineSplit[1]);
						comps.add(lineSplit[0]);
					} else {
						List comps = new ArrayList();
						comps.add(lineSplit[0]);
						groups2Components.put(lineSplit[1], comps);
					}
				}
			}
			in.close();
		} catch (IOException e) {
			throw new IOException("Problem reading list of voice import components -- importMain.config seems broken", e);
		}
		String[][] result = new String[groups.size()][];
		for (int i = 0; i < groups.size(); i++) {
			String groupKey = groups.get(i);
			String groupName = groups2Names.get(groupKey);
			List components = groups2Components.get(groupKey);
			if (components == null) // group is empty
				continue;
			String[] group = new String[components.size() + 1];
			group[0] = groupName;
			for (int j = 0; j < components.size(); j++) {
				group[j + 1] = components.get(j);
			}
			result[i] = group;
		}
		return result;
	}

	public static void main(String[] args) throws Exception {
		File voiceDir = determineVoiceBuildingDir(args);
		if (voiceDir == null) {
			throw new IllegalArgumentException("Cannot determine voice building directory.");
		}
		File wavDir = new File(voiceDir, "wav");
		// System.out.println(System.getProperty("user.dir")+System.getProperty("file.separator")+"wav");
		assert wavDir.exists() : "no wav dir at " + wavDir.getAbsolutePath();

		/* Read the list of components */
		File importMainConfigFile = new File(voiceDir, "importMain.config");
		if (!importMainConfigFile.exists()) {
			FileUtils.copyInputStreamToFile(DatabaseImportMain.class.getResourceAsStream("importMain.config"),
					importMainConfigFile);
		}
		assert importMainConfigFile.exists();

		String[][] groups2comps = readComponentList(new FileInputStream(importMainConfigFile));

		VoiceImportComponent[] components = createComponents(groups2comps);

		/* Load DatabaseLayout */
		File configFile = new File(voiceDir, "database.config");

		DatabaseLayout db = new DatabaseLayout(configFile, components);
		if (!db.isInitialized())
			return;

		if (args.length > 0) { // non-gui mode: arguments are expected to be component names, in order or application
			for (String compName : args) {
				VoiceImportComponent component = null;
				for (VoiceImportComponent comp : components) {
					if (comp.getName().equals(compName)) {
						component = comp;
						break;
					}
				}
				if (component != null) {
					System.out.println("Running " + compName);
					component.compute();
				} else {
					throw new IllegalArgumentException("No such voice import component: " + compName);
				}

			}
		} else {
			/* Display GUI */
			String voicename = db.getProp(db.VOICENAME);
			DatabaseImportMain importer = new DatabaseImportMain("Database import: " + voicename, components, db, groups2comps);
			importer.pack();
			// Center window on screen:
			importer.setLocationRelativeTo(null);
			importer.setVisible(true);
		}

	}

	/**
	 * @param groups2comps
	 *            groups2comps
	 * @return compsList.toArray(new VoiceImportComponent[compsList.size()])
	 * @throws InstantiationException
	 *             InstantiationException
	 * @throws IllegalAccessException
	 *             IllegalAccessException
	 * @throws ClassNotFoundException
	 *             ClassNotFoundException
	 */
	private static VoiceImportComponent[] createComponents(String[][] groups2comps) throws InstantiationException,
			IllegalAccessException, ClassNotFoundException {
		/* Create component classes */
		List compsList = new ArrayList();
		// loop over the groups
		for (int i = 0; i < groups2comps.length; i++) {
			// get the components for this group
			String[] nextComps = groups2comps[i];
			// loop over the components (first element is group name; ignore)
			for (int j = 1; j < nextComps.length; j++) {
				// get the class name of this component
				String className = nextComps[j];
				// System.out.println(className);
				// create a new instance of this class and store in compsList
				compsList.add((VoiceImportComponent) Class.forName(className).newInstance());
				// remove "de.dfki...." from class name and store in groups2comps
				nextComps[j] = className.substring(className.lastIndexOf('.') + 1);
			}
		}
		return compsList.toArray(new VoiceImportComponent[compsList.size()]);
	}

	private static File determineVoiceBuildingDir(String[] args) {
		// Determine the voice building directory in the following order:
		// 1. System property "user.dir"
		// 2. First command line argument
		// 3. current directory
		// 4. Prompt user via gui.
		// Do a sanity check -- do they exist, do they have a wav/ subdirectory?

		String voiceBuildingDir = null;
		Vector candidates = new Vector();
		candidates.add(System.getProperty("user.dir"));
		if (args.length > 0)
			candidates.add(args[0]);
		candidates.add("."); // current directory
		for (String dir : candidates) {
			if (dir != null && new File(dir).isDirectory() && new File(dir + "/wav").isDirectory()) {
				voiceBuildingDir = dir;
				break;
			}
		}
		if (voiceBuildingDir == null) { // need to ask user
			JFrame window = new JFrame("This is the Frames's Title Bar!");
			JFileChooser fc = new JFileChooser();
			fc.setDialogTitle("Choose Voice Building Directory");
			fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			System.out.println("Opening GUI....... ");
			// outDir.setText(file.getAbsolutePath());
			// System.exit(0);
			int returnVal = fc.showOpenDialog(window);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File file = fc.getSelectedFile();
				if (file != null)
					voiceBuildingDir = file.getAbsolutePath();
			}
		}
		System.setProperty("user.dir", voiceBuildingDir);
		if (voiceBuildingDir != null) {
			return new File(voiceBuildingDir);
		} else {
			return null;
		}
	}

	class ConfigButtonActionListener implements ActionListener {
		private String comp;

		public ConfigButtonActionListener(String comp) {
			this.comp = comp;
		}

		public void actionPerformed(ActionEvent ae) {
			currentComponent = comp;
			displaySettingsGUI();
		}
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy