- package mpi.eudico.client.annotator.viewer;
- import mpi.eudico.client.annotator.Constants;
- import mpi.eudico.client.annotator.ElanLocale;
- import mpi.util.LogUtil;
- import java.io.BufferedInputStream;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.FileWriter;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutputStream;
- import java.net.URL;
- import java.util.Hashtable;
- import java.util.logging.Logger;
- import javax.swing.JFileChooser;
- import javax.swing.JFrame;
- import javax.swing.JOptionPane;
- /**
- * A class to start the Praat executable and open the .wav file that has been
- * loaded into Elan.<br>
- * Opening a file and (possibly) selecting a part from that file is a two step
- * process. First we have to make sure that Praat is/has been started, next we
- * have to use the sendpraat executable to let Praat execute a script with the
- * right arguments. At least on Windows it is not possible to start Praat
- * with the script etc. as arguments. The Windows praatcon.exe Praat console
- * executable can start Praat with a script etc., but it can not load a 'long
- * sound' and create a view and editor for it.<br>
- * Since elan only loads sound files that are on a local file system it is
- * save to expect that a provided url is on the local file system.
- *
- * @author Han Sloetjes
- * @version jul 2004
- */
- public class PraatConnection {
- /** constant for the name of the praat sript */
- private static final String PRAAT_SCRIPT = "openpraat.praat";
- /** constant for a script to create a clip from a sound file */
- public static final String PRAAT_CLIP_SCRIPT = "createsoundclip.praat";
- private static String scriptFileName;
- /** constant for the Praat application path property */
- private static final String PRAAT_APP = "Praat app";
- /** constant for the sendpraat application path property */
- private static final String SENDPRAAT_APP = "Sendpraat app";
- /** Holds value of property DOCUMENT ME! */
- private static final String PRAAT_PREFS_FILE = Constants.ELAN_DATA_DIR +
- Constants.FILESEPARATOR + "praat.pfs";
- /**
- * a non-thread-safe way of temporarily storing the result of a check on
- * the running state of Praat (Unix systems)
- */
- static boolean isPraatRunning = false;
- /** the logger */
- private static final Logger LOG = Logger.getLogger(PraatConnection.class.getName());
- private static Hashtable preferences;
- /**
- * Creates a new PraatConnection instance
- */
- private PraatConnection() {
- }
- /**
- * Asynchronously opens a file in Praat.
- *
- * @param fileName the media file
- * @param begintime the selection begintime
- * @param endtime the selection end time
- */
- public static void openInPraat(final String fileName, final long begintime,
- final long endtime) {
- new Thread() {
- public void run() {
- if (!checkScript()) {
- JOptionPane.showMessageDialog(new JFrame(),
- ElanLocale.getString(
- "PraatConnection.Message.NoScript"),
- ElanLocale.getString("Message.Warning"),
- JOptionPane.WARNING_MESSAGE);
- LOG.warning("Praat script could not be created");
- return;
- }
- if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
- openWindowsPraat(fileName, begintime, endtime);
- } else {
- openOtherPraat(fileName, begintime, endtime);
- }
- }
- }.start();
- }
- /**
- * Asynchronously creates clip from a file with Praat and opens the new file as a Sound object.
- *
- * @param fileName the media file
- * @param begintime the selection begintime
- * @param endtime the selection end time
- */
- public static void clipWithPraat(final String fileName,
- final long begintime, final long endtime) {
- new Thread() {
- public void run() {
- if (!checkClipScript()) {
- JOptionPane.showMessageDialog(new JFrame(),
- ElanLocale.getString(
- "PraatConnection.Message.NoScript"),
- ElanLocale.getString("Message.Warning"),
- JOptionPane.WARNING_MESSAGE);
- LOG.warning("Praat script could not be created");
- return;
- }
- if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
- openWindowsPraat(fileName, begintime, endtime);
- } else {
- openOtherPraat(fileName, begintime, endtime);
- }
- }
- }.start();
- }
- /**
- * For windows flavors some processing of path names should be done etc.
- *
- * @param fileName the media file
- * @param begintime the begintime of the selection
- * @param endtime the end time of the selection
- */
- private static void openWindowsPraat(String fileName, long begintime,
- long endtime) {
- if (fileName != null) {
- // Praat can handle files on samba shares too
- if (fileName.startsWith("///")) {
- fileName = fileName.substring(3);
- }
- fileName = fileName.replace('/', '\\');
- // sendpraat has problems with filepaths containing spaces
- // single or double quotes don't seem to help
- // if the file name itself contains spaces there seems to be no solution
- if (fileName.indexOf(' ') > 0) {
- fileName = spacelessWindowsPath(fileName);
- }
- //System.out.println("file: " + fileName);
- } else {
- LOG.warning("Praat: media file is null");
- return;
- }
- // first make sure praat is running
- String praatExe = getPreference(PRAAT_APP);
- if ((praatExe == null) || (praatExe.length() == 0)) {
- praatExe = "Praat.exe";
- }
- String[] praatCom = new String[] { praatExe };
- try {
- Runtime.getRuntime().exec(praatCom);
- // give praat a moment to start
- try {
- Thread.sleep(2000);
- } catch (InterruptedException ie) {
- LOG.info(LogUtil.formatStackTrace(ie));
- }
- //
- } catch (SecurityException se) {
- JOptionPane.showMessageDialog(new JFrame(),
- ElanLocale.getString("PraatConnection.Message.Security"),
- ElanLocale.getString("Message.Warning"),
- JOptionPane.WARNING_MESSAGE);
- LOG.warning(LogUtil.formatStackTrace(se));
- return;
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- // not found, prompt
- String path = locatePraat();
- if (path == null) {
- return;
- } else {
- // retry
- openWindowsPraat(fileName, begintime, endtime);
- return;
- }
- }
- // next execute sendpraat
- // (on windows we cannot use praatcon.exe for this task)
- String sendpraatExe = getPreference(SENDPRAAT_APP);
- if ((sendpraatExe == null) || (sendpraatExe.length() == 0)) {
- sendpraatExe = "sendpraat.exe";
- }
- String executeCom = "execute " + scriptFileName + " " + fileName + " " +
- String.valueOf(begintime) + " " + String.valueOf(endtime);
- String[] sendpraatCom = new String[3];
- sendpraatCom[0] = sendpraatExe;
- sendpraatCom[1] = "Praat";
- sendpraatCom[2] = executeCom;
- try {
- Runtime.getRuntime().exec(sendpraatCom);
- } catch (SecurityException se) {
- JOptionPane.showMessageDialog(new JFrame(),
- ElanLocale.getString("PraatConnection.Message.Security"),
- ElanLocale.getString("Message.Warning"),
- JOptionPane.WARNING_MESSAGE);
- LOG.warning(LogUtil.formatStackTrace(se));
- return;
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- // not found, prompt
- String path = locateSendpraat();
- if (path == null) {
- return;
- } else {
- // retry
- openWindowsPraat(fileName, begintime, endtime);
- }
- }
- }
- /**
- * Open Praat on non-windows systems; MacOS X, Unix, Linux. <br>
- * Note: on Mac OS X every call to runtime.exec to start Praat opens a new
- * instance of Praat: it is not detected that it is already open (this is
- * a result of the fact that you can not use the Praat.app "folder" to
- * start Praat). Maybe we should not try to start Praat but let the user
- * be responsible to start Praat.
- *
- * @param fileName the media file
- * @param begintime the begintime of the selection
- * @param endtime the end time of the selection
- */
- private static void openOtherPraat(String fileName, long begintime,
- long endtime) {
- if (fileName != null) {
- // Praat can handle files on samba shares too
- // on Mac: when the url starts with 3 slashes, remove 2 slashes
- // TO DO: this needs testing on other platforms
- if (fileName.startsWith("///")) {
- fileName = fileName.substring(2);
- }
- } else {
- LOG.warning("Praat: media file is null");
- return;
- }
- // first make sure praat is running
- String praatExe = getPreference(PRAAT_APP);
- if ((praatExe == null) || (praatExe.length() == 0)) {
- praatExe = "praat";
- }
- // check whether praat is running already; this is not a thread safe way to check
- isPraatRunning = false;
- checkUnixPraatProcess();
- try {
- Thread.sleep(700);
- } catch (InterruptedException ie) {
- }
- if (!isPraatRunning) {
- String[] praatCom = new String[] { praatExe };
- try {
- Runtime.getRuntime().exec(praatCom);
- // give praat a moment to start
- try {
- Thread.sleep(1500);
- } catch (InterruptedException ie) {
- LOG.info(LogUtil.formatStackTrace(ie));
- }
- } catch (SecurityException se) {
- JOptionPane.showMessageDialog(new JFrame(),
- ElanLocale.getString("PraatConnection.Message.Security"),
- ElanLocale.getString("Message.Warning"),
- JOptionPane.WARNING_MESSAGE);
- LOG.warning(LogUtil.formatStackTrace(se));
- return;
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- // not found, prompt
- String path = locatePraat();
- if (path == null) {
- return;
- } else {
- // retry
- openOtherPraat(fileName, begintime, endtime);
- return;
- }
- }
- }
- // next execute sendpraat
- String sendpraatExe = getPreference(SENDPRAAT_APP);
- if ((sendpraatExe == null) || (sendpraatExe.length() == 0)) {
- sendpraatExe = "sendpraat";
- }
- // test this om other platforms...
- String executeCom = "execute " + scriptFileName + " " + fileName + " " +
- String.valueOf(begintime) + " " + String.valueOf(endtime);
- String[] sendpraatCom = new String[3];
- sendpraatCom[0] = sendpraatExe;
- sendpraatCom[1] = "praat";
- sendpraatCom[2] = executeCom;
- try {
- Runtime.getRuntime().exec(sendpraatCom);
- } catch (SecurityException se) {
- JOptionPane.showMessageDialog(new JFrame(),
- ElanLocale.getString("PraatConnection.Message.Security"),
- ElanLocale.getString("Message.Warning"),
- JOptionPane.WARNING_MESSAGE);
- LOG.warning(LogUtil.formatStackTrace(se));
- return;
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- // not found, prompt
- String path = locateSendpraat();
- if (path == null) {
- return;
- } else {
- // retry
- openOtherPraat(fileName, begintime, endtime);
- }
- }
- }
- /**
- * Checks whether or not the praatscript file already exists. When not it
- * is created in the elan directory in the user's home directory.
- *
- * @return true if the file already existed or could be created, false
- * otherwise
- */
- private static boolean checkScript() {
- if (!checkHome()) {
- return false;
- }
- scriptFileName = Constants.ELAN_DATA_DIR + Constants.FILESEPARATOR +
- PRAAT_SCRIPT;
- if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
- // Praat on Windows does not like spaces in the path
- if (scriptFileName.indexOf(' ') > -1) {
- String dir = System.getProperty("java.io.tmpdir");
- if (dir != null) {
- scriptFileName = dir + Constants.FILESEPARATOR +
- PRAAT_SCRIPT;
- }
- // or
- // scriptFileName = spacelessWindowsPath(scriptFileName);
- }
- }
- File file = new File(scriptFileName);
- if (file.exists()) {
- return true;
- } else {
- // first try to copy the file from the .jar
- if (copyScriptFromJar(file,
- "/mpi/eudico/client/annotator/resources/openpraat.praat")) {
- return true;
- } else {
- // fallback: create the file programmatically
- return createScriptFile(file);
- }
- }
- }
- /**
- * Checks whether or not the praat clip script file already exists. When not it
- * is created in the elan directory in the user's home directory.
- *
- * @return true if the file already existed or could be created, false
- * otherwise
- */
- private static boolean checkClipScript() {
- if (!checkHome()) {
- return false;
- }
- scriptFileName = Constants.ELAN_DATA_DIR + Constants.FILESEPARATOR +
- PRAAT_CLIP_SCRIPT;
- if (System.getProperty("os.name").toLowerCase().indexOf("windows") > -1) {
- // Praat on Windows does not like spaces in the path
- if (scriptFileName.indexOf(' ') > -1) {
- String dir = System.getProperty("java.io.tmpdir");
- if (dir != null) {
- scriptFileName = dir + Constants.FILESEPARATOR +
- PRAAT_SCRIPT;
- }
- // or
- // scriptFileName = spacelessWindowsPath(scriptFileName);
- }
- }
- File file = new File(scriptFileName);
- if (file.exists()) {
- return true;
- } else {
- // first try to copy the file from the .jar
- if (copyScriptFromJar(file,
- "/mpi/eudico/client/annotator/resources/createsoundclip.praat")) {
- return true;
- } else {
- return false;
- }
- }
- }
- /**
- * Checks whether the elan home dir exists. When not create it.
- *
- * @return true if the dir already existed or could be created, false
- * otherwise
- */
- private static boolean checkHome() {
- File dataDir = new File(Constants.ELAN_DATA_DIR);
- if (!dataDir.exists()) {
- try {
- dataDir.mkdir();
- } catch (Exception e) {
- LOG.warning(LogUtil.formatStackTrace(e));
- return false;
- }
- }
- return true;
- }
- /**
- * Tries to copy the script file from the jar.
- *
- * @param copyFile the copy of the script
- * @param resource the fully qualified name of the resource
- *
- * @return true if the operation succeeded, false otherwise
- */
- private static boolean copyScriptFromJar(File copyFile, String resource) {
- BufferedInputStream inStream;
- FileOutputStream out;
- try {
- copyFile.createNewFile();
- URL scriptSrc = PraatConnection.class.getResource(resource);
- if (scriptSrc == null) {
- LOG.warning("No script source file found");
- return false;
- }
- inStream = new BufferedInputStream(scriptSrc.openStream());
- byte[] buf = new byte[512];
- int n;
- out = new FileOutputStream(copyFile);
- while ((n = inStream.read(buf)) > -1) {
- out.write(buf, 0, n);
- }
- out.flush();
- out.close();
- inStream.close();
- return true;
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- return false;
- }
- }
- /**
- * Writes the script file to the elan home dir.
- *
- * @param scriptFile the file to write to
- *
- * @return true if everything went allright, false otherwise
- */
- private static boolean createScriptFile(File scriptFile) {
- try {
- if (!scriptFile.exists()) {
- scriptFile.createNewFile();
- }
- String contents = createScriptContents();
- FileWriter writer = new FileWriter(scriptFile);
- writer.write(contents);
- writer.close();
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- return false;
- }
- return true;
- }
- /**
- * Create the script. Temp. could be copied from the jar...
- *
- * @return the scriptcontents
- */
- private static String createScriptContents() {
- StringBuffer scriptBuffer = new StringBuffer();
- scriptBuffer.append("form Segment info\n");
- scriptBuffer.append("\ttext Filename \"\"\n");
- scriptBuffer.append("\tpositive Start 0\n");
- scriptBuffer.append("\tpositive End 10\n");
- scriptBuffer.append("endform\n");
- scriptBuffer.append("len = length( filename$)\n");
- scriptBuffer.append("dot = rindex (filename$, \".\")\n");
- scriptBuffer.append("slash = rindex (filename$, \"/\")\n");
- scriptBuffer.append("if slash == 0\n");
- scriptBuffer.append("\tslash = rindex (filename$, \"\\\")\n");
- scriptBuffer.append("endif\n");
- scriptBuffer.append(
- "stem$ = mid$ (filename$ , slash+1, dot - slash - 1 )\n");
- //scriptBuffer.append("stem$ = replace$ (stem$, \".\", \"_\", 0)");
- scriptBuffer.append("Open long sound file... 'filename$'\n");
- scriptBuffer.append("s = start / 1000\n");
- scriptBuffer.append("en = end / 1000\n");
- scriptBuffer.append("View\n");
- scriptBuffer.append("editor LongSound 'stem$'\n");
- scriptBuffer.append("\tSelect... 's' 'en'\n");
- scriptBuffer.append("\tZoom to selection\n");
- scriptBuffer.append("endeditor");
- return scriptBuffer.toString();
- }
- /**
- * Promt the user for the location of the Praat executable.
- *
- * @return the path to the Praat executable
- */
- private static String locatePraat() {
- String praatPath = null;
- JFileChooser chooser = new JFileChooser();
- chooser.setDialogTitle(ElanLocale.getString(
- "PraatConnection.LocateDialog.Title1"));
- chooser.setApproveButtonText(ElanLocale.getString(
- "PraatConnection.LocateDialog.Select"));
- int option = chooser.showOpenDialog(new JFrame());
- if (option == JFileChooser.CANCEL_OPTION) {
- // cannot remove a preference yet
- setPreference(PRAAT_APP, "");
- } else {
- File path = chooser.getSelectedFile();
- praatPath = path.getAbsolutePath();
- // Mac specific addition
- if (path.isDirectory() && praatPath.endsWith(".app")) {
- // append path to the actual executable
- praatPath += "/Contents/MacOS/Praat";
- }
- // trust the user, cannot possibly check the value
- setPreference(PRAAT_APP, praatPath);
- }
- return praatPath;
- }
- /**
- * Promt the user for the location of the sendpraat executable.
- *
- * @return the path to the sendpraat executable
- */
- private static String locateSendpraat() {
- String sendpraatPath = null;
- JFileChooser chooser = new JFileChooser();
- chooser.setDialogTitle(ElanLocale.getString(
- "PraatConnection.LocateDialog.Title2"));
- chooser.setApproveButtonText(ElanLocale.getString(
- "PraatConnection.LocateDialog.Select"));
- int option = chooser.showOpenDialog(new JFrame());
- if (option == JFileChooser.CANCEL_OPTION) {
- // cannot remove a preference yet
- setPreference(SENDPRAAT_APP, "");
- } else {
- File path = chooser.getSelectedFile();
- sendpraatPath = path.getAbsolutePath();
- // trust the user, cannot possibly check the value
- setPreference(SENDPRAAT_APP, sendpraatPath);
- }
- return sendpraatPath;
- }
- /**
- * Returns the pref for the specified key like the Praat and sendpraat
- * executable paths from the praat pref file.
- *
- * @param key the key for the pref
- *
- * @return the pref
- */
- private static String getPreference(String key) {
- if (key == null) {
- return null;
- }
- if (preferences == null) {
- preferences = loadPreferences();
- }
- return (String) preferences.get(key);
- }
- /**
- * Loads the praat preferences from the praat pref file.
- *
- * @return a hashtable with the pref mappings
- */
- private static Hashtable loadPreferences() {
- Hashtable hashtable = new Hashtable();
- ;
- File inFile = new File(PRAAT_PREFS_FILE);
- try {
- //if (inFile.exists()) {
- FileInputStream inStream = new FileInputStream(inFile);
- ObjectInputStream objectIn = new ObjectInputStream(inStream);
- hashtable = (Hashtable) objectIn.readObject();
- objectIn.close();
- inStream.close();
- //}
- } catch (FileNotFoundException fnfe) {
- LOG.warning("Could not load Praat preferences");
- LOG.warning(LogUtil.formatStackTrace(fnfe));
- } catch (IOException ioe) {
- LOG.warning("Could not load Praat preferences");
- LOG.warning(LogUtil.formatStackTrace(ioe));
- } catch (ClassNotFoundException cnfe) {
- LOG.warning("Could not load Praat preferences");
- LOG.warning(LogUtil.formatStackTrace(cnfe));
- }
- return hashtable;
- }
- /**
- * Sets the specified pref to the new value.
- *
- * @param key the pref key
- * @param value the pref value
- */
- private static void setPreference(String key, String value) {
- if ((key == null) || (value == null)) {
- return;
- }
- if (preferences == null) {
- preferences = new Hashtable();
- }
- preferences.put(key, value);
- savePreferences();
- }
- /**
- * Wrties the praat preferences file to disc.
- */
- private static void savePreferences() {
- if (preferences == null) {
- return;
- }
- try {
- FileOutputStream outStream = new FileOutputStream(PRAAT_PREFS_FILE);
- ObjectOutputStream objectOut = new ObjectOutputStream(outStream);
- objectOut.writeObject(preferences);
- objectOut.close();
- outStream.close();
- } catch (FileNotFoundException fnfe) {
- LOG.warning("Could not save Praat preferences");
- LOG.warning(LogUtil.formatStackTrace(fnfe));
- } catch (IOException ioe) {
- LOG.warning("Could not save Praat preferences");
- LOG.warning(LogUtil.formatStackTrace(ioe));
- }
- }
- /**
- * Tries to check whether or not Praat is already running using the Unix
- * utility <code>top</code>.
- */
- private static void checkUnixPraatProcess() {
- try {
- final Process p = Runtime.getRuntime().exec(new String[] {
- "top", "-l1"
- });
- new Thread(new Runnable() {
- public void run() {
- try {
- InputStreamReader isr = new InputStreamReader(p.getInputStream());
- BufferedReader br = new BufferedReader(isr);
- String line = null;
- while ((line = br.readLine()) != null) {
- if (line.indexOf(" Praat ") > 0) {
- br.close();
- isPraatRunning = true;
- break;
- }
- }
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- }
- }
- }).start();
- } catch (SecurityException sex) {
- LOG.warning(LogUtil.formatStackTrace(sex));
- } catch (IOException ioe) {
- LOG.warning(LogUtil.formatStackTrace(ioe));
- }
- }
- /**
- * Converts a file path containing spaces in directory names to a path with
- * "DIRECT~x" elements. The filename itself will not be converted.
- *
- * @param fileName the file path with spaces
- *
- * @return a converted path
- */
- private static String spacelessWindowsPath(String fileName) {
- if (fileName == null) {
- return null;
- }
- //String path = fileName;
- int firstSpace = fileName.indexOf(' ');
- if (firstSpace 0) {
- return fileName;
- }
- int prevSep = fileName.lastIndexOf(File.separator, firstSpace);
- int nextSep = fileName.indexOf(File.separator, firstSpace);
- String fileOrDirName = null;
- if (nextSep > 0) {
- fileOrDirName = fileName.substring(prevSep + 1, nextSep);
- } else {
- //fileOrDirName = fileName.substring(prevSep + 1);
- return fileName;
- }
- // if an tilde already has been added, prevSep + 1 does not include the file separator ??
- try {
- File dir = new File(fileName.substring(0, prevSep + 1));
- if (!dir.isDirectory()) {
- return fileName;
- }
- String start = fileOrDirName.substring(0, fileOrDirName.indexOf(' '));
- String[] fNames = dir.list();
- int sufNum = 0;
- for (int i = 0; i fNames.length; i++) {
- if (fNames[i].startsWith(fileOrDirName)) {
- sufNum++;
- if (fNames[i].equals(fileOrDirName)) {
- break;
- }
- }
- }
- StringBuffer pathBuf = new StringBuffer(dir.getPath());
- // see comment above
- if (pathBuf.charAt(pathBuf.length() - 1) != File.separatorChar) {
- pathBuf.append(File.separator);
- }
- if (start.length() = 6) {
- String tmp = fileOrDirName.replaceAll(" ", "");
- if (tmp.length() = 6) {
- pathBuf.append(tmp.toUpperCase()).append("~").append(sufNum);
- } else {
- pathBuf.append(tmp.substring(0, 6).toUpperCase()).append("~")
- .append(sufNum);
- }
- } else {
- pathBuf.append(start.substring(0, 6).toUpperCase()).append("~")
- .append(sufNum);
- }
- if (nextSep > 0) {
- pathBuf.append(fileName.substring(nextSep));
- }
- if (pathBuf.indexOf(" ") 0) {
- return pathBuf.toString();
- } else {
- return spacelessWindowsPath(pathBuf.toString());
- }
- } catch (Exception ex) {
- LOG.warning("Invalid directory: " + ex.getMessage());
- return fileName;
- }
- }
- }
Tuesday, July 10, 2012
Build Java connection with praat voice analyzer
Subscribe to:
Posts (Atom)