/** * 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 <http://www.gnu.org/licenses/>. * */ package marytts.tools.redstart; import org.apache.commons.io.FilenameUtils; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.text.DecimalFormat; import java.util.Properties; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.SourceDataLine; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.ListSelectionModel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableColumn; import marytts.signalproc.display.MultiDisplay; import marytts.util.data.audio.MonoAudioInputStream; import marytts.util.string.StringUtils; /** * * @author Mat Wilson <mwilson@dfki.de> */ public class AdminWindow extends javax.swing.JFrame { // ______________________________________________________________________ // Instance fields // ______________________________________________________________________ // Class fields // Column indices for prompt set table protected static final int REC_STATUS_COLUMN = 0; // First column is recording status protected static final int BASENAME_COLUMN = 1; // Second column is basename protected static final int PROMPT_TEXT_COLUMN = 2; // Third collumn is prompt text private JTable jTable_PromptSet; // Create our own table programmatically // Path for folder containing the voice - use AdminWindow.getVoiceFolderPath().getPath() to access externally private String voiceFolderPathString; // e.g., "/project/mary/mat/voices/bundesliga" // Folder names (below the level of the voice folder) private static final String PROMPT_FOLDER_NAME = "/text/"; private static final String REC_FOLDER_NAME = "/wav/"; private static final String SYNTH_FOLDER_NAME = "/prompt_wav/"; private static final String TRANSCRIPTION_FOLDER_NAME = "/transcription/"; private static boolean beepDemoOn = true; // Flag for toggling beep demo (clicking on status icon) // Forms and related fields private SpeakerWindow speakerWin = new SpeakerWindow(); // Speaker window instance private Options optionsDialog; // Boolean flags used for determining when buttons should be enabled and disabled private boolean playingStatus = false; // Boolean flag to indicate if playback is underway private boolean continuousMode = false; // Boolean flag to indicate if playback is underway private boolean recordingBlock = false; // Boolean flag to indicate if playback is part of a recording block // More objects protected Prompt[] promptArray; // For storing the loaded prompt set private RecSession currentSession; // Recording session object private boolean stopPressed; // Internal setting, set to true by stop button private Font defaultPromptFont; private static boolean showTranscription = false; // if true show the transcription if they are available // showTranscription: if the input file text contains also the transcription, there is the possibility of see them private static boolean redAlertMode = false; // if true show red alert portion of text // redAlert mode: if the input file text refers to the redalert mode (sensitive text portion surrounded by underscore char) // there is the possibility of visualize them with a red color // ______________________________________________________________________ // Constructors /** * Creates new form AdminWindow and starts the recording session * * @param voiceFolderPathString * voiceFolderPathString */ public AdminWindow(String voiceFolderPathString) { this.voiceFolderPathString = voiceFolderPathString; optionsDialog = new Options(this); setSystemLookAndFeel(); System.out.println("Initializing components..."); // GUI form setup initComponents(); // Initialize GUI components (auto-generated code) initMoreComponents(); // Initialize some components further (editable) setupVoice(); jTable_PromptSet.requestFocusInWindow(); Test.output("|AdminWindow| Ready for testing."); // TESTCODE } private void setupVoice() { this.currentSession = createRecSession(); // Create new recording session System.out.println("Components initialized."); buildPromptTable(); // Set up and fill the prompt table // PRI4 - Encapsulate this better; poor design but functional this.speakerWin.setupProgressBar(this.promptArray.length); this.speakerWin.updateProgressBar(1); // Because we start at first prompt this.speakerWin.updatePromptCount(1); System.out.println("System is ready."); } public void setShowTranscription(boolean selected) { // TODO Auto-generated method stub showTranscription = selected; } public boolean getShowTranscription() { // TODO Auto-generated method stub return showTranscription; } public void setRedAlertMode(boolean selected) { // TODO Auto-generated method stub redAlertMode = selected; } public boolean getRedAlertMode() { return redAlertMode; } /** * Updates the prompt table with prompt data * * @param newSession * The current recording session object * @return newSession */ private RecSession createRecSession() { RecSession newSession = null; try { newSession = new RecSession(this); } catch (FileNotFoundException ex) { String message = "File not found."; showMessage(message, true); // true = warning if (Test.isDebug) { ex.printStackTrace(); } } catch (IOException ex) { String message = "File read error."; showMessage(message, true); // true = warning if (Test.isDebug) { ex.printStackTrace(); } } Test.output("|AdminWindow| Recording session created."); // TESTCODE return newSession; } /** Programmatically set the column widths of the prompt set table */ private void setColumnWidths() { // only try to do this when we are visible if (!this.isVisible()) return; // Get columns from column model TableColumn recStatusColumn = jTable_PromptSet.getColumnModel().getColumn(0); TableColumn baseNameColumn = jTable_PromptSet.getColumnModel().getColumn(1); TableColumn promptColumn = jTable_PromptSet.getColumnModel().getColumn(2); // Get length of longest string in the column int widestBasename = LookAndFeel.getMaxColumnWidth(this.jTable_PromptSet, this.BASENAME_COLUMN); // These widths seem to be appropriate for the firs two columns - set them int recStatusColumnWidth = 50; // Leave hardcoded since only three possible values int baseNameColumnWidth = widestBasename + 10; // was 110 when hardcorded Test.output("Basename column width: " + widestBasename); recStatusColumn.setPreferredWidth(recStatusColumnWidth); baseNameColumn.setPreferredWidth(baseNameColumnWidth); // Now set prompt column to fill remaining width of the table int scrollbarBuffer = 3; // Buffer to avoid displaying a horizontal scrollbar int tableWidth = jScrollPane_PromptSet.getWidth(); promptColumn.setPreferredWidth(tableWidth - (recStatusColumnWidth + baseNameColumnWidth + scrollbarBuffer)); } /** * Determines recording status given how many recordings a prompt has, as well as clipping status * * @param rec * The number of files a prompt has * @return The appropriate string, indicating the prompt's recording status */ protected static String determineStatus(Recording rec) { String recStatus; String clipStatus; String combinedStatus; int fileCount = rec.getFileCount(); // First determine recording status (number of recordings) if (fileCount == 0) { // Recording status is "" recStatus = ""; } else if (fileCount == 1) { // Recording status is "R" recStatus = "R"; // "R" indicates 1 recording exists } else { // Recording status is "R+" recStatus = "R+"; // "R+" indicates >1 recording exists } if (fileCount > 0) { // Now determine clipping status (audio or temporal clipping) rec.checkForAmpClipping(); rec.checkForTempClipping(); } // Determine message content related to clipping status if ((rec.isAmpClipped) || (rec.isTempClipped)) { clipStatus = "!"; // Show "!" if either amplitude or temporal clipping } else if (rec.isAmpWarning) { clipStatus = "?"; // Show "?" if amplitude clipping almost occurred (near threshold) } else { clipStatus = ""; // Otherwise no clipping of any sort } // Create the combined status combinedStatus = recStatus + clipStatus; Test.output("|AdminWindow.determineStatus| Combined status: " + combinedStatus); return combinedStatus; } // Specifically for SpeakerWindow.java to determine if it should show prompt count public Options getOptions() { return this.optionsDialog; } public SpeakerWindow getSpeakerWindow() { return speakerWin; } /** * Gets the currently selected row in the prompt set table * * @return jTable_PromptSet.getSelectedRow() */ public int getCurrentRow() { return jTable_PromptSet.getSelectedRow(); } /** Displays the prompt text in the prompt display pane */ private void displayPromptText() { int currentRow = getCurrentRow(); if (currentRow == -1) return; Prompt prompt = promptArray[currentRow]; // Current prompt String promptText = prompt.getPromptText(); Recording rec = prompt.getRecording(); // Most recent recording for selected prompt String nextPromptText = ""; if (currentRow + 1 < promptArray.length) { nextPromptText = promptArray[currentRow + 1].getPromptText(); } // Transcription if flag set and if file present String promptTranscription = "\n<"; String nextPromptTranscription = "\n<"; if (showTranscription) { promptTranscription = promptTranscription + promptArray[currentRow].getPromptTranscriptionText(); if (currentRow + 1 < promptArray.length) nextPromptTranscription = nextPromptTranscription + promptArray[currentRow + 1].getPromptTranscriptionText(); } promptTranscription = promptTranscription + ">"; nextPromptTranscription = nextPromptTranscription + ">"; jTextPane_PromptDisplay.setFont(defaultPromptFont); if (this.isVisible()) { if (!showTranscription) { LookAndFeel.centerPromptText(jTextPane_PromptDisplay, promptText, redAlertMode); LookAndFeel.centerPromptText(jTextPane_nextSentence, nextPromptText, redAlertMode); } else { LookAndFeel.centerPromptText(jTextPane_PromptDisplay, promptText + promptTranscription, redAlertMode); LookAndFeel.centerPromptText(jTextPane_nextSentence, nextPromptText + nextPromptTranscription, redAlertMode); } } // Also update in Speaker window if (!showTranscription) this.speakerWin.updatePromptDisplay(promptText, nextPromptText, redAlertMode); else this.speakerWin.updatePromptDisplay(promptText + promptTranscription, nextPromptText + nextPromptTranscription, redAlertMode); int promptNumber = getCurrentRow() + 1; this.speakerWin.updateProgressBar(promptNumber); this.speakerWin.updatePromptCount(promptNumber); // Display number of recordings in the message bar int recCount = prompt.getRecCount(); String inflectedRecordings = " recordings"; if (recCount == 1) { inflectedRecordings = " recording"; } String clippingMessage = ""; // No clipping messasge (changed below if clipping) boolean warning = false; // Warning flag to show correct icon (false = info; true = warning) // If a recording exists if (recCount > 0) { // Enable play button jButton_Play.setEnabled(true); jButton_Display.setEnabled(true); // Get clipping status of most recent recording clippingMessage = getClippingMessage(rec); warning = rec.isAmpClipped || rec.isTempClipped; // Set warning level accordingly } else { jButton_Play.setEnabled(false); // Disable Play button if no recording to play jButton_Display.setEnabled(false); } String message = "Ready: " + prompt.getBasename() + " selected (" + recCount + inflectedRecordings + "). " + clippingMessage; showMessage(message, warning); // false = info, not a warning; true = warning (clipping) } /** * Further initialization of components on startup (These can be edited in NetBeans, initComponents() cannot) */ private void initMoreComponents() { // Center window in the user's screen Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension frameSize = getSize(); setLocation(new Point((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2)); // Set application icon in title bar left-hand corner this.setIconImage(Toolkit.getDefaultToolkit().getImage(IconSet.LOGO_16x16_URL)); // Change status icon in Admin window jLabel_SessionStatus.setIcon(IconSet.STOP_48X48); defaultPromptFont = jTextPane_PromptDisplay.getFont(); speakerWin.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { jCheckBoxMenuItem_SpeakerWindow.setSelected(false); } }); optionsDialog.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent evt) { speakerWin.showOrHidePromptCount(); } }); } private void buildPromptTable() { this.promptArray = this.currentSession.getPromptArray(); System.out.println("Loading prompts..."); Test.output("Array contains " + promptArray.length + " prompts."); // Make column names array String[] columnNames = new String[3]; columnNames[REC_STATUS_COLUMN] = "Status"; columnNames[BASENAME_COLUMN] = "Basename"; columnNames[PROMPT_TEXT_COLUMN] = "Prompt Preview"; // Now create the table itself JTable table = new JTable(new PromptTableModel(promptArray, columnNames, redAlertMode)); table.setColumnSelectionAllowed(false); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // Set alignment for the status colum to centered DefaultTableCellRenderer renderer = new ClippingColorRenderer(); renderer.setHorizontalAlignment(JTextField.CENTER); table.getColumnModel().getColumn(REC_STATUS_COLUMN).setCellRenderer(renderer); // Set selection highlight colour to light blue table.setSelectionBackground(new java.awt.Color(153, 204, 255)); // Add listeners table.getSelectionModel().addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { displayPromptText(); } }); // Store the table in an instance field accessible to the entire class this.jTable_PromptSet = table; Thread recordingStatusInitialiser = new Thread() { public void run() { updateAllRecStatus(); } }; recordingStatusInitialiser.start(); // Display table in the appropriate component pane jScrollPane_PromptSet.setViewportView(table); if (promptArray.length > 0) { table.setRowSelectionInterval(0, 0); // Show first row of prompt table as selected displayPromptText(); // Display the prompt text for the first prompt in the prompt display pane } setColumnWidths(); System.out.println("Total " + table.getRowCount() + " prompts loaded."); } private void updateAllRecStatus() { for (int row = 0; row < promptArray.length; row++) { String recStatus = determineStatus(promptArray[row].getRecording()); // PRI2 Assumes saturation status is false; needs to actually check jTable_PromptSet.setValueAt(recStatus, row, REC_STATUS_COLUMN); } } /** Updates session status icon and calls method to play a synthesized file */ private void playSynthesis() { preparePlayback(); Prompt selectedPrompt = promptArray[getCurrentRow()]; String basename = selectedPrompt.getBasename(); // Change status icon in Admin window jLabel_SessionStatus.setIcon(IconSet.PLAY_48X48); // Change status icon in Speaker window speakerWin.updateSessionStatus(IconSet.PLAY_64X64); // PRI2 Get path name with DatabaseLayout method instead? String synthFolderPathString = getSynthFolderPath().getPath(); // Synthesis files are prepended with "p_" (e.g., p_spike0001.wav) String soundFilePathString = synthFolderPathString + File.separator + "p_" + basename + ".wav"; SourceDataLine speakerOutput = optionsDialog.getSpeakerOutputLine(); Speech.play(soundFilePathString, speakerOutput, optionsDialog.getSpeakerOutputMode()); // TESTCODE Test.output("|AdminWindow.playSynthesis| [Synthesis]:" + selectedPrompt.getPromptText()); // Change status icon in Admin window jLabel_SessionStatus.setIcon(IconSet.STOP_48X48); // Change status icon in Speaker window speakerWin.updateSessionStatus(IconSet.STOP_64X64); // Enforce pause after synthesis playback (as set by user in Options dialog) try { Thread.sleep(optionsDialog.getPauseAfterSynth()); } catch (InterruptedException ex) { ex.printStackTrace(); } } /** * Stops playback Separate method needed to stop recording */ private void stopPlayback() { Speech.stopPlaying(); // Immediately stop any playback stopPressed = true; } /** Calls methods for making a recording */ private void makeRecording() { // Get currently selected prompt int promptIndex = getCurrentRow(); Prompt currentPrompt = this.promptArray[promptIndex]; String currentBasename = currentPrompt.getBasename(); // Change status icon in Admin Window jLabel_SessionStatus.setIcon(IconSet.REC_48X48); // Change status icon in Speaker Window speakerWin.updateSessionStatus(IconSet.REC_64X64); int nChars = currentPrompt.getPromptText().length(); // Calculate mic open time, using bufferToAdd from the user options int micOpenTime = nChars * optionsDialog.getTimePerChar() + optionsDialog.getBufferToAdd(); Test.output("|AdminWindow.makeRecording()| nChars: " + nChars + " a " + optionsDialog.getTimePerChar() + " ms"); Test.output("|AdminWindow.makeRecording()| buffer: " + optionsDialog.getBufferToAdd() + " ms"); Test.output("|AdminWindow.makeRecording()| micOpenTime: " + micOpenTime + " ms"); // Create recording object and rename any latest recording Recording currentRecording = currentPrompt.getRecording(); if (currentRecording.getFileCount() > 0) currentRecording.archiveLatestRecording(); try { boolean warning = false; // Update button text (change from "Record" to "Stop") toggleRecordToStop(); // Update message bar String openDuration = new DecimalFormat("#.###").format(micOpenTime * 0.001); String message = "Recording for " + currentBasename + ": Microphone open for " + openDuration + " s..."; showMessage(message, warning); // warning = false; just info // TESTCODE Test.output("|AdminWindow.makeRecording| [Recording]:" + currentPrompt.getPromptText()); // Open the microphone currentRecording.timedRecord(optionsDialog.getTargetDataLine(), optionsDialog.getInlineFilter(), micOpenTime); // Update recording status for current prompt currentRecording.updateFileCount(); String recStatus = determineStatus(currentRecording); message = getClippingMessage(currentRecording); warning = currentRecording.isAmpClipped || currentRecording.isTempClipped; Test.output("|AdminWindow.makeRecording()| New status: " + recStatus); jTable_PromptSet.setValueAt(recStatus, promptIndex, REC_STATUS_COLUMN); // Enable Play button only if at least one recording exists for selected basename if ((currentRecording.getFileCount() > 0) && (!this.recordingBlock)) { jButton_Play.setEnabled(true); jButton_Display.setEnabled(true); } // TESTCODE Test.output("|AdminWindow.makeRecording| " + currentBasename + " now has " + currentRecording.getFileCount() + " file(s)"); // Finished recording // Update message bar message = "Recording for " + currentBasename + ": Microphone is closed. " + message; showMessage(message, warning); // false = info, not a warning; true if clipping occurred } catch (Exception ex) { ex.printStackTrace(); String message = "Recording error. Check your audio options and see the console for details."; showMessage(message, true); // true = warning, not info } // Change status icon in Admin window and Speaker Window jLabel_SessionStatus.setIcon(IconSet.STOP_48X48); speakerWin.updateSessionStatus(IconSet.STOP_64X64); // Only do below if option is not selected to continue with next prompt if (!this.jCheckBox_ContinueWithNext.isSelected()) { // Re-enable the Play/Stop button this.jButton_Play.setEnabled(true); jButton_Display.setEnabled(true); // Update button text (change from "Stop" to "Record") toggleStopToRecord(); } } /** Plays latest recording for the currently selected promtp */ private void playRecording() { preparePlayback(); Prompt selectedPrompt = promptArray[getCurrentRow()]; String basename = selectedPrompt.getBasename(); int recCount = selectedPrompt.getRecCount(); // TESTCODE Test.output("|AdminWindow.playRecording| Number of recordings for " + basename + " is: " + recCount); // If selected prompt has a recording if (recCount > 0) { // Change status icon in Admin Window jLabel_SessionStatus.setIcon(IconSet.PLAY_48X48); // Change status icon in Speaker Window speakerWin.updateSessionStatus(IconSet.PLAY_64X64); // Update message bar String message = "Playing latest recording for " + basename + "."; showMessage(message, false); // false = info, not a warning // Determine complete path for the .wav file String recFolderPathString = getRecFolderPath().getPath(); String soundFilePathString = recFolderPathString + File.separator + basename + ".wav"; // TESTCODE Test.output("|AdminWindow.playRecording| Sound file path: " + soundFilePathString); try { if (!this.recordingBlock) { // We're using the Play button as the Stop button // Update button text (change from "Play" to "Stop") togglePlayToStop(); } SourceDataLine expertOutput = optionsDialog.getExpertOutputLine(); Speech.play(soundFilePathString, expertOutput, optionsDialog.getExpertOutputMode()); // Update message bar message = "Ready."; showMessage(message, false); // false = info, not a warning // PRI3 Change this to show current selection (as before) } catch (Exception ex) { ex.printStackTrace(); message = "Playback error. Check your audio options and see the console for details."; showMessage(message, true); // true = warning, not info } // Change status icon in Admin window jLabel_SessionStatus.setIcon(IconSet.STOP_48X48); // Change status icon in Speaker window speakerWin.updateSessionStatus(IconSet.STOP_64X64); } else { // Update message bar String message = "No recording for " + basename + "."; showMessage(message, false); // false = info, not a warning } endPlayback(); } /** Establishes logic for running a recording (with optional playback, etc.) */ private void manageRecording() { this.recordingBlock = true; // To help know which buttons to enable and disable this.stopPressed = false; setCheckBoxes(false); int startingRow = getCurrentRow(); int endRow = startingRow + 1; // When user has selected "Continue with next prompt" if (jCheckBox_ContinueWithNext.isSelected()) { // Get number of rows so that we continue to the end of the prompt set endRow = this.promptArray.length; } for (int row = startingRow; !stopPressed && row < endRow; row++) { // TESTCODE Test.output("|AdminWindow.jButton_RecordActionPerformed| [Current row]:" + row); Test.output("|AdminWindow.jButton_RecordActionPerformed| [End row]:" + endRow); // Get currently selected prompt int promptIndex = getCurrentRow(); Prompt currentPrompt = this.promptArray[promptIndex]; // Update prompt display displayPromptText(); // Play synthesized prompt if this option is enabled if (jCheckBox_PlaySynthesis.isSelected()) { playSynthesis(); } else if (row > startingRow) { // Apply user-defined silence before recording, only for non-initial recording try { // Indicate pause duration in the message bar String silenceDuration = new DecimalFormat("#.###").format(optionsDialog.getSilenceDuration() * 0.001); String message = currentPrompt.getBasename() + ": " + silenceDuration + " s pause to allow reading of the prompt..."; showMessage(message, false); // warning = false; just info // Enforce the pause duration between prompt recordings (as set by user in Options dialog) Thread.sleep(optionsDialog.getSilenceDuration()); } catch (InterruptedException ex) { ex.printStackTrace(); } } if (!stopPressed) { // Disable the Play/Stop button so that user can't accidentally begin playing the file we're overwriting this.jButton_Play.setEnabled(false); jButton_Display.setEnabled(false); // Play beep to indicate microphone is open optionsDialog.playOpenBeep(); } if (!stopPressed) { // Call method that coordinates the actual recording makeRecording(); // Play beep to indicate microphone is closed (if option selected in GUI if (jCheckBox_PlayClosingBeep.isSelected()) { optionsDialog.playClosedBeep(); Test.output("Second beep enabled."); } else { Test.output("Second beep disabled."); } } // Listen to recording if this option is selected if (!stopPressed && jCheckBox_PlayBackRec.isSelected()) { playRecording(); } // TESTCODE else Test.output("|AdminWindow.jButton_RecordActionPerformed| [No playback of recording]"); // Select next row if ((row < (endRow - 1)) && (!stopPressed)) { jTable_PromptSet.setRowSelectionInterval(row + 1, row + 1); // Advance vertical scrollbar try { int column = 1; // jTable_PromptSet.getSelectedColumn(); Rectangle cellRect = jTable_PromptSet.getCellRect(row + 4, column, false); jTable_PromptSet.scrollRectToVisible(cellRect); jTable_PromptSet.updateUI(); } catch (Exception ex) { ex.printStackTrace(); } } } // row // Re-enable buttons in the event they were disabled due to continuous mode this.jButton_Record.setEnabled(true); this.jButton_Play.setEnabled(true); jButton_Display.setEnabled(true); // Update button text (change from "Stop" to "Record" or "Play") toggleStopToRecord(); toggleStopToPlay(); setCheckBoxes(true); this.recordingBlock = false; this.continuousMode = false; } /** * 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. */ // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents private void initComponents() { jPanel_SpeakerView = new javax.swing.JPanel(); jTextPane_PromptDisplay = new javax.swing.JTextPane(); jTextPane_nextSentence = new javax.swing.JTextPane(); jLabel_SessionStatus = new javax.swing.JLabel(); jPanel_AdminControls = new javax.swing.JPanel(); jScrollPane_PromptSet = new javax.swing.JScrollPane(); jCheckBox_PlaySynthesis = new javax.swing.JCheckBox(); jCheckBox_PlayBackRec = new javax.swing.JCheckBox(); jCheckBox_ContinueWithNext = new javax.swing.JCheckBox(); jButton_Record = new javax.swing.JButton(); jButton_Play = new javax.swing.JButton(); jSeparator_MessageBar = new javax.swing.JSeparator(); jLabel_MessageBar = new javax.swing.JLabel(); jCheckBox_PlayClosingBeep = new javax.swing.JCheckBox(); jLabel_MessageBarIcon = new javax.swing.JLabel(); jButton_Display = new javax.swing.JButton(); jMenuBar_AdminWindow = new javax.swing.JMenuBar(); jMenu_File = new javax.swing.JMenu(); jMenuItem_Open = new javax.swing.JMenuItem(); jMenuItem_ImportText = new javax.swing.JMenuItem(); jSeparator_File = new javax.swing.JSeparator(); jMenuItem_Exit = new javax.swing.JMenuItem(); jMenu_Tools = new javax.swing.JMenu(); jMenuItem_Options = new javax.swing.JMenuItem(); jMenu_Window = new javax.swing.JMenu(); jCheckBoxMenuItem_AdminWindow = new javax.swing.JCheckBoxMenuItem(); jCheckBoxMenuItem_SpeakerWindow = new javax.swing.JCheckBoxMenuItem(); jMenu_Help = new javax.swing.JMenu(); jMenu_About = new javax.swing.JMenuItem(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("Redstart - Admin Window"); addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { formComponentResized(evt); } }); addFocusListener(new java.awt.event.FocusAdapter() { public void focusGained(java.awt.event.FocusEvent evt) { formFocusGained(evt); } }); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { formWindowClosing(evt); } }); jPanel_SpeakerView.setBorder(javax.swing.BorderFactory.createTitledBorder("Speaker View")); jTextPane_PromptDisplay.setBorder(javax.swing.BorderFactory.createEtchedBorder()); jTextPane_PromptDisplay.setEditable(false); jTextPane_PromptDisplay.setFont(new java.awt.Font("Tahoma", 0, 30)); jTextPane_PromptDisplay .setText("This is a long and boring test sentence, the only purpose of which is to see how to break between lines without making any difference across the windows."); jTextPane_PromptDisplay.setAutoscrolls(false); jTextPane_PromptDisplay.addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(java.awt.event.ComponentEvent evt) { jTextPane_PromptDisplayComponentResized(evt); } }); jTextPane_nextSentence.setBackground(new java.awt.Color(245, 245, 245)); jTextPane_nextSentence.setBorder(javax.swing.BorderFactory.createEtchedBorder()); jTextPane_nextSentence.setEditable(false); jTextPane_nextSentence.setFont(new java.awt.Font("Tahoma", 0, 24)); jTextPane_nextSentence.setForeground(new java.awt.Color(50, 50, 50)); jTextPane_nextSentence .setText("This is a long and boring test sentence, the only purpose of which is to see how to break between lines without making any difference across the windows."); jLabel_SessionStatus.setIcon(new javax.swing.ImageIcon(getClass() .getResource("/marytts/tools/redstart/stopped_48x48.png"))); jLabel_SessionStatus.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { jLabel_SessionStatusMouseClicked(evt); } }); org.jdesktop.layout.GroupLayout jPanel_SpeakerViewLayout = new org.jdesktop.layout.GroupLayout(jPanel_SpeakerView); jPanel_SpeakerView.setLayout(jPanel_SpeakerViewLayout); jPanel_SpeakerViewLayout.setHorizontalGroup(jPanel_SpeakerViewLayout.createParallelGroup( org.jdesktop.layout.GroupLayout.LEADING).add( org.jdesktop.layout.GroupLayout.TRAILING, jPanel_SpeakerViewLayout .createSequentialGroup() .addContainerGap() .add(jPanel_SpeakerViewLayout .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(org.jdesktop.layout.GroupLayout.TRAILING, jTextPane_PromptDisplay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 773, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel_SpeakerViewLayout .createSequentialGroup() .add(jTextPane_nextSentence, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 624, Short.MAX_VALUE).add(101, 101, 101).add(jLabel_SessionStatus))) .addContainerGap())); jPanel_SpeakerViewLayout.setVerticalGroup(jPanel_SpeakerViewLayout.createParallelGroup( org.jdesktop.layout.GroupLayout.LEADING).add( org.jdesktop.layout.GroupLayout.TRAILING, jPanel_SpeakerViewLayout .createSequentialGroup() .add(jTextPane_PromptDisplay, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jPanel_SpeakerViewLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) .add(jLabel_SessionStatus) .add(jTextPane_nextSentence, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 124, Short.MAX_VALUE)) .addContainerGap())); jPanel_AdminControls.setBorder(javax.swing.BorderFactory.createTitledBorder("Admin Controls")); jScrollPane_PromptSet.setFocusCycleRoot(true); jScrollPane_PromptSet.setNextFocusableComponent(jButton_Record); jCheckBox_PlaySynthesis.setText("Play synthesized prompt"); jCheckBox_PlaySynthesis.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jCheckBox_PlaySynthesis.setMargin(new java.awt.Insets(0, 0, 0, 0)); jCheckBox_PlayBackRec.setText("Play back after recording"); jCheckBox_PlayBackRec.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jCheckBox_PlayBackRec.setMargin(new java.awt.Insets(0, 0, 0, 0)); jCheckBox_ContinueWithNext.setSelected(true); jCheckBox_ContinueWithNext.setText("Continue with next prompt"); jCheckBox_ContinueWithNext.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jCheckBox_ContinueWithNext.setMargin(new java.awt.Insets(0, 0, 0, 0)); jCheckBox_ContinueWithNext.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jCheckBox_ContinueWithNextActionPerformed(evt); } }); jButton_Record.setIcon(new javax.swing.ImageIcon(getClass().getResource("/marytts/tools/redstart/recording_16x16.png"))); jButton_Record.setText("Record"); jButton_Record.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); jButton_Record.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); jButton_Record.setMaximumSize(new java.awt.Dimension(95, 25)); jButton_Record.setMinimumSize(new java.awt.Dimension(95, 25)); jButton_Record.setPreferredSize(new java.awt.Dimension(95, 25)); jButton_Record.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton_RecordActionPerformed(evt); } }); jButton_Play.setIcon(new javax.swing.ImageIcon(getClass().getResource("/marytts/tools/redstart/playing_16x16.png"))); jButton_Play.setText("Play"); jButton_Play.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); jButton_Play.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT); jButton_Play.setMaximumSize(new java.awt.Dimension(95, 25)); jButton_Play.setMinimumSize(new java.awt.Dimension(95, 25)); jButton_Play.setPreferredSize(new java.awt.Dimension(95, 25)); jButton_Play.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton_PlayActionPerformed(evt); } }); jLabel_MessageBar.setText("Ready."); jCheckBox_PlayClosingBeep.setSelected(true); jCheckBox_PlayClosingBeep.setText("Play beep when microphone is closed"); jCheckBox_PlayClosingBeep.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); jCheckBox_PlayClosingBeep.setMargin(new java.awt.Insets(0, 0, 0, 0)); jLabel_MessageBarIcon.setText("Message:"); jButton_Display.setText("Display"); jButton_Display.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jButton_DisplayActionPerformed(evt); } }); org.jdesktop.layout.GroupLayout jPanel_AdminControlsLayout = new org.jdesktop.layout.GroupLayout(jPanel_AdminControls); jPanel_AdminControls.setLayout(jPanel_AdminControlsLayout); jPanel_AdminControlsLayout.setHorizontalGroup(jPanel_AdminControlsLayout.createParallelGroup( org.jdesktop.layout.GroupLayout.LEADING).add( org.jdesktop.layout.GroupLayout.TRAILING, jPanel_AdminControlsLayout .createSequentialGroup() .addContainerGap() .add(jPanel_AdminControlsLayout .createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) .add(jScrollPane_PromptSet, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 773, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.LEADING, jSeparator_MessageBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 773, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.LEADING, jPanel_AdminControlsLayout.createSequentialGroup().add(jLabel_MessageBarIcon) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED).add(jLabel_MessageBar)) .add(jPanel_AdminControlsLayout .createSequentialGroup() .add(jPanel_AdminControlsLayout .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jCheckBox_PlaySynthesis).add(jCheckBox_PlayBackRec) .add(jCheckBox_PlayClosingBeep).add(jCheckBox_ContinueWithNext)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 410, Short.MAX_VALUE) .add(jPanel_AdminControlsLayout .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jButton_Display, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 98, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(org.jdesktop.layout.GroupLayout.TRAILING, jButton_Record, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .add(org.jdesktop.layout.GroupLayout.TRAILING, jButton_Play, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))).addContainerGap())); jPanel_AdminControlsLayout.setVerticalGroup(jPanel_AdminControlsLayout.createParallelGroup( org.jdesktop.layout.GroupLayout.LEADING).add( org.jdesktop.layout.GroupLayout.TRAILING, jPanel_AdminControlsLayout .createSequentialGroup() .add(jScrollPane_PromptSet, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 95, Short.MAX_VALUE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jPanel_AdminControlsLayout .createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false) .add(jPanel_AdminControlsLayout .createSequentialGroup() .add(jButton_Record, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jButton_Play, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) .add(org.jdesktop.layout.GroupLayout.LEADING, jPanel_AdminControlsLayout .createSequentialGroup() .add(jCheckBox_PlaySynthesis) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jCheckBox_PlayClosingBeep) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(jCheckBox_PlayBackRec))) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jPanel_AdminControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) .add(jCheckBox_ContinueWithNext).add(jButton_Display)) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jSeparator_MessageBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jPanel_AdminControlsLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) .add(jLabel_MessageBar).add(jLabel_MessageBarIcon)).addContainerGap())); jPanel_AdminControlsLayout.linkSize(new java.awt.Component[] { jButton_Play, jButton_Record }, org.jdesktop.layout.GroupLayout.VERTICAL); jMenu_File.setText("File"); jMenuItem_Open.setIcon(new javax.swing.ImageIcon(getClass().getResource("/marytts/tools/redstart/open_16x16.png"))); jMenuItem_Open.setText("Open Voice..."); jMenuItem_Open.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem_OpenActionPerformed(evt); } }); jMenu_File.add(jMenuItem_Open); jMenuItem_ImportText.setText("Import text file..."); jMenuItem_ImportText.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem_ImportTextActionPerformed(evt); } }); jMenu_File.add(jMenuItem_ImportText); jMenu_File.add(jSeparator_File); jMenuItem_Exit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/marytts/tools/redstart/exit_16x16.png"))); jMenuItem_Exit.setText("Exit"); jMenuItem_Exit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem_ExitActionPerformed(evt); } }); jMenu_File.add(jMenuItem_Exit); jMenuBar_AdminWindow.add(jMenu_File); jMenu_Tools.setText("Tools"); jMenuItem_Options.setIcon(new javax.swing.ImageIcon(getClass().getResource("/marytts/tools/redstart/options_16x16.png"))); jMenuItem_Options.setText("Options..."); jMenuItem_Options.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem_OptionsActionPerformed(evt); } }); jMenu_Tools.add(jMenuItem_Options); jMenuBar_AdminWindow.add(jMenu_Tools); jMenu_Window.setText("Window"); jCheckBoxMenuItem_AdminWindow.setSelected(true); jCheckBoxMenuItem_AdminWindow.setText("Admin Window"); jCheckBoxMenuItem_AdminWindow.setEnabled(false); jMenu_Window.add(jCheckBoxMenuItem_AdminWindow); jCheckBoxMenuItem_SpeakerWindow.setText("Speaker Window"); jCheckBoxMenuItem_SpeakerWindow.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jCheckBoxMenuItem_SpeakerWindowActionPerformed(evt); } }); jMenu_Window.add(jCheckBoxMenuItem_SpeakerWindow); jMenuBar_AdminWindow.add(jMenu_Window); jMenu_Help.setText("Help"); jMenu_About.setIcon(new javax.swing.ImageIcon(getClass().getResource("/marytts/tools/redstart/about_16x16.png"))); jMenu_About.setText("About Redstart"); jMenu_About.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenu_AboutActionPerformed(evt); } }); jMenu_Help.add(jMenu_About); jMenuBar_AdminWindow.add(jMenu_Help); setJMenuBar(jMenuBar_AdminWindow); org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add( layout.createSequentialGroup() .addContainerGap() .add(layout .createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING) .add(org.jdesktop.layout.GroupLayout.LEADING, jPanel_AdminControls, 0, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .add(org.jdesktop.layout.GroupLayout.LEADING, jPanel_SpeakerView, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap())); layout.setVerticalGroup(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING).add( org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() .add(jPanel_SpeakerView, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) .add(jPanel_AdminControls, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) .addContainerGap())); pack(); }// </editor-fold>//GEN-END:initComponents private void formFocusGained(java.awt.event.FocusEvent evt) {// GEN-FIRST:event_formFocusGained jTable_PromptSet.requestFocusInWindow(); }// GEN-LAST:event_formFocusGained private void jMenuItem_ImportTextActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem_ImportTextActionPerformed JFileChooser fc = new JFileChooser(new File(voiceFolderPathString)); fc.setDialogTitle("Choose text file to import"); // fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int returnVal = fc.showOpenDialog(this); if (returnVal != JFileChooser.APPROVE_OPTION) return; File file = fc.getSelectedFile(); if (file == null) return; String[] lines = null; try { lines = StringUtils.readTextFile(file.getAbsolutePath(), "UTF-8"); } catch (IOException ioe) { ioe.printStackTrace(); } if (lines == null || lines.length == 0) return; Object[] options = new Object[] { "Keep first column", "Discard first column" }; int answer = JOptionPane.showOptionDialog(this, "File contains " + lines.length + " sentences.\n" + "Sample line:\n" + lines[0] + "\n" + "Keep or discard first column?", "Import details", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]); boolean discardFirstColumn = (answer == JOptionPane.NO_OPTION); String prefix = (String) JOptionPane.showInputDialog(this, "Prefix to use for individual sentence filenames:", "Choose filename prefix", JOptionPane.PLAIN_MESSAGE, null, null, "s"); int numDigits = (int) Math.log10(lines.length) + 1; String pattern = prefix + "%0" + numDigits + "d.txt"; File scriptFile = new File(voiceFolderPathString + "/" + file.getName() + ".script.txt"); PrintWriter scriptWriter = null; try { scriptWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(scriptFile), "UTF-8")); } catch (IOException e) { JOptionPane.showMessageDialog(this, "Cannot write to script file " + scriptFile.getAbsolutePath() + ":\n" + e.getMessage()); if (scriptWriter != null) scriptWriter.close(); return; } File textFolder = getPromptFolderPath(); // if filename ends with ".txt_tr" then it has also transcriptions in it String selectedFile_ext = FilenameUtils.getExtension(file.getName()); Boolean inputHasAlsoTranscription = false; File transcriptionFolder = new File(""); // transcription folder name, and makedir if (selectedFile_ext.equals("txt_tr")) { System.out.println("txt_tr"); if (lines.length % 2 == 0) { // even } else { // odd System.err.println(".txt_tr file has an odd number of lines, so it's corrupted, exiting."); System.exit(0); } inputHasAlsoTranscription = true; String transcriptionFolderName = voiceFolderPathString + AdminWindow.TRANSCRIPTION_FOLDER_NAME; transcriptionFolder = new File(transcriptionFolderName); if (transcriptionFolder.exists()) { System.out.println("transcription folder already exists"); } else { if (transcriptionFolder.mkdirs()) { System.out.println("transcription folder created"); } else { System.err.println("Cannot create transcription folder -- exiting."); System.exit(0); } } } else { System.out.println("input file extension is not txt_tr, but " + selectedFile_ext + ", so it contains ortographic sentences without transcriptions."); } for (int i = 0; i < lines.length; i++) { String line = lines[i]; if (discardFirstColumn) line = line.substring(line.indexOf(' ') + 1); int sent_index = i + 1; if (inputHasAlsoTranscription == true) { sent_index = i / 2 + 1; } String filename = String.format(pattern, sent_index); System.out.println(filename + " " + line); File textFile = new File(textFolder, filename); if (textFile.exists()) { JOptionPane.showMessageDialog(this, "Cannot writing file " + filename + ":\n" + "File exists!\n" + "Aborting text file import."); return; } PrintWriter pw = null; try { pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(textFile), "UTF-8")); pw.println(line); scriptWriter.println(filename.substring(0, filename.lastIndexOf('.')) + " " + line); } catch (IOException ioe) { JOptionPane.showMessageDialog(this, "Error writing file " + filename + ":\n" + ioe.getMessage()); ioe.printStackTrace(); return; } finally { if (pw != null) pw.close(); } // transcription case: if (inputHasAlsoTranscription == true) { // modify pattern: best would be something like sed "s/.txt$/.tr$/" // easy but dirty: String transc_pattern = pattern.replace(".txt", ".tr"); filename = String.format(transc_pattern, sent_index); i++; line = lines[i]; if (discardFirstColumn) line = line.substring(line.indexOf(' ') + 1); File transcriptionTextFile = new File(transcriptionFolder, filename); if (transcriptionTextFile.exists()) { JOptionPane.showMessageDialog(this, "Cannot writing file " + transcriptionTextFile.getName() + ":\n" + "File exists!\n" + "Aborting text file import."); return; } pw = null; try { pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(transcriptionTextFile), "UTF-8")); pw.println(line); scriptWriter.println(filename.substring(0, filename.lastIndexOf('.')) + " " + line); } catch (IOException ioe) { JOptionPane.showMessageDialog(this, "Error writing file " + filename + ":\n" + ioe.getMessage()); ioe.printStackTrace(); return; } finally { if (pw != null) pw.close(); } } } scriptWriter.close(); setupVoice(); }// GEN-LAST:event_jMenuItem_ImportTextActionPerformed private void jButton_DisplayActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton_DisplayActionPerformed Prompt selectedPrompt = promptArray[getCurrentRow()]; try { File f = selectedPrompt.getRecording().getFile(); AudioInputStream audio = AudioSystem.getAudioInputStream(f); if (audio.getFormat().getChannels() > 1) { audio = new MonoAudioInputStream(audio, optionsDialog.getInputMode()); } MultiDisplay d = new MultiDisplay(audio, selectedPrompt.getBasename(), false); } catch (Exception e) { e.printStackTrace(); } }// GEN-LAST:event_jButton_DisplayActionPerformed private void jTextPane_PromptDisplayComponentResized(java.awt.event.ComponentEvent evt) {// GEN-FIRST:event_jTextPane_PromptDisplayComponentResized // this.displayPromptText(); }// GEN-LAST:event_jTextPane_PromptDisplayComponentResized private void jCheckBox_ContinueWithNextActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jCheckBox_ContinueWithNextActionPerformed if (this.jCheckBox_ContinueWithNext.isSelected()) { this.continuousMode = true; } else { this.continuousMode = false; } }// GEN-LAST:event_jCheckBox_ContinueWithNextActionPerformed private void jLabel_SessionStatusMouseClicked(java.awt.event.MouseEvent evt) {// GEN-FIRST:event_jLabel_SessionStatusMouseClicked // Play a beep (for demo purposes to the speaker; also useful for quickly testing audio setup) if (beepDemoOn) { optionsDialog.playOpenBeep(); if (jCheckBox_PlayClosingBeep.isSelected()) { beepDemoOn = false; } } else { optionsDialog.playClosedBeep(); beepDemoOn = true; } }// GEN-LAST:event_jLabel_SessionStatusMouseClicked private void formWindowClosing(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_formWindowClosing System.out.println("Exiting Recording Session Manager... Done."); }// GEN-LAST:event_formWindowClosing private void jMenuItem_OpenActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem_OpenActionPerformed // Allow user to choose a different voice (prompt set) without exiting the tool // Create a file chooser final JFileChooser openDialog = new JFileChooser(); // Set the current directory to the voice currently in use openDialog.setCurrentDirectory(getVoiceFolderPath()); openDialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int result = openDialog.showDialog(AdminWindow.this, "Open Voice"); if (result == JFileChooser.APPROVE_OPTION) { File voice = openDialog.getSelectedFile(); setVoiceFolderPath(voice); // Set to the selected the voice folder path Test.output("Open voice: " + voice); setupVoice(); } else { Test.output("Open command cancelled."); } }// GEN-LAST:event_jMenuItem_OpenActionPerformed /** * Exits the application * * @param evt * An action event */ private void jMenuItem_ExitActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem_ExitActionPerformed System.out.println("Exiting Recording Session Manager... Done."); System.exit(0); }// GEN-LAST:event_jMenuItem_ExitActionPerformed /** * Shows an options dialog * * @param evt * An action event */ private void jMenuItem_OptionsActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem_OptionsActionPerformed optionsDialog.setVisible(true); }// GEN-LAST:event_jMenuItem_OptionsActionPerformed /** * Shows a simple About dialog for the application * * @param evt * An action event */ private void jMenu_AboutActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenu_AboutActionPerformed // PRI4 Could show a more elaborate dialog // More info, DFKI logo, etc. // JOptionPane.showMessageDialog(this, "Recording Session Manager\n(c) 2007 DFKI GmbH"); new About(this).setVisible(true); }// GEN-LAST:event_jMenu_AboutActionPerformed /* * Activates or deactivates the speaker window, depending on current state * * @param evt Action event */ private void jCheckBoxMenuItem_SpeakerWindowActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jCheckBoxMenuItem_SpeakerWindowActionPerformed // Activate speaker window if checkbox menu item was not selected // Else close speaker window if checkbox menu item was already selected if (jCheckBoxMenuItem_SpeakerWindow.isSelected()) { speakerWin.updateSessionStatus(IconSet.STOP_64X64); speakerWin.setVisible(true); } else { speakerWin.setVisible(false); } }// GEN-LAST:event_jCheckBoxMenuItem_SpeakerWindowActionPerformed /** * Resizes columns to fit expected data * * @param evt * Component event */ private void formComponentResized(java.awt.event.ComponentEvent evt) {// GEN-FIRST:event_formComponentResized // Note: event also appears to include component initialization, not just resizing if (this.isVisible()) { setColumnWidths(); displayPromptText(); // Re-center prompt text } }// GEN-LAST:event_formComponentResized public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { setColumnWidths(); displayPromptText(); } } /* * Interrupts recording or playback * * @param evt Action event */ /** * Plays the latest recorded version of the currently selected prompt * * @param evt * evt */ private void jButton_PlayActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton_PlayActionPerformed if (this.playingStatus) { stopPlayback(); // Stop playback if underway this.stopPressed = true; toggleStopToRecord(); // Needed if Play/Stop is pressed during continuous record mode this.jButton_Record.setEnabled(true); toggleStopToPlay(); } // Otherwise play the recording else { togglePlayToStop(); new Thread() { public void run() { playRecording(); } }.start(); } }// GEN-LAST:event_jButton_PlayActionPerformed /** * Handles the recording logic, including potential playback and continuous mode (if selected) * * @param evt * Action event */ private void jButton_RecordActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton_RecordActionPerformed if (this.playingStatus) { stopRecord(); // Stop recording if underway this.stopPressed = true; this.playingStatus = false; // PRI3 Can we combine these two flags or is stopPressed needed for setupRecording()? toggleStopToRecord(); toggleStopToPlay(); // Disable Record button so that user can't press it while waiting to stop this.jButton_Record.setEnabled(false); // Re-enabled at end of manageRecording(); // Temporary solution until method implemented to stop actual recording String message = "Stop button pressed."; showMessage(message, true); // true = warning, not info } // Otherwise make the recording else { // Don't toggle yet if playing synthesized prompt first if (!jCheckBox_ContinueWithNext.isSelected()) { toggleRecordToStop(); } new Thread() { public void run() { manageRecording(); } }.start(); Test.output("Dispatched recording thread"); } }// GEN-LAST:event_jButton_RecordActionPerformed /** Sets the GUI look and feel to that of the system (e.g., Windows XP, Mac OS) */ private void setSystemLookAndFeel() { // Get the properties from the options file Properties options = new Properties(); try { // First, load defaults from resource in classpath: options.load(Redstart.class.getResourceAsStream("user.options")); // Then, overwrite from file if present: File fileHandle = new File(optionsDialog.getOptionsPathString()); if (fileHandle.exists()) { FileInputStream optionsStream; try { optionsStream = new FileInputStream(fileHandle); options.load(optionsStream); // Close the input stream optionsStream.close(); } catch (FileNotFoundException ex) { ex.printStackTrace(); } } } catch (IOException ex) { ex.printStackTrace(); } String systemLookAndFeelProp = options.getProperty("systemLookAndFeel"); if (systemLookAndFeelProp.equals("true")) { // Use the look and feel of the system try { // Set to system look and feel UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } } } /** * Returns path for folder containing basenames and prompts * * @return Folder path containing basenames and prompts (e.g., /project/mary/mat/voices/bundesliga/text) */ public File getPromptFolderPath() { // Create the instructions folder path from the voice folder path String pathString = voiceFolderPathString + AdminWindow.PROMPT_FOLDER_NAME; File promptFolderPath = new File(pathString); return promptFolderPath; } /** * Returns file path for folder containing the speaker recordings * * @return File path for folder containing the speaker recordings (e.g., /project/mary/mat/voices/bundesliga/wav) */ public File getRecFolderPath() { // Create the recordings folder path from the voice folder path String pathString = voiceFolderPathString + AdminWindow.REC_FOLDER_NAME; File recFolderPath = new File(pathString); // TESTCODE Test.output("|AdminWindow.getRecFolderPath()| Recordings Path = " + recFolderPath.getPath()); return recFolderPath; } /** * Returns file path for folder containing the synthesized recordings * * @return File path for folder containing the synthesized recordings (e.g., /project/mary/mat/voices/bundesliga/prompt_wav) */ public File getSynthFolderPath() { // Create the recordings folder path from the voice folder path String pathString = voiceFolderPathString + AdminWindow.SYNTH_FOLDER_NAME; File synthFolderPath = new File(pathString); // TESTCODE Test.output("|AdminWindow.getSynthFolderPath()| Synthesis Path = " + synthFolderPath.getPath()); return synthFolderPath; } /** * Returns file path for folder containing the synthesized recordings * * @return File path for folder containing the synthesized recordings (e.g., /project/mary/mat/voices/bundesliga/prompt_wav) */ public File getTranscriptionFolderPath() { // Create the recordings folder path from the voice folder path String pathString = voiceFolderPathString + AdminWindow.TRANSCRIPTION_FOLDER_NAME; File transcriptionFolderPath = new File(pathString); // TESTCODE Test.output("|AdminWindow.getTranscriptionFolderPath()| Transcription Path = " + transcriptionFolderPath.getPath()); return transcriptionFolderPath; } /** * Returns file path for folder containing the voice * * @return File path for folder containing the voice (e.g., /project/mary/mat/voices/bundesliga) */ public File getVoiceFolderPath() { return new File(voiceFolderPathString); } protected void setVoiceFolderPath(File newPath) { // PRI2 Check that the path is valid // Set the new path voiceFolderPathString = newPath.getPath(); optionsDialog.saveVoicePath(newPath); } public void deselectSpeakerWindow() { // Deselect Speaker Window in Window menu now that window has been closed by the user this.jMenu_Window.setSelected(false); } private void stopRecord() { Recording currentRecording = promptArray[getCurrentRow()].getRecording(); currentRecording.stopRecording(); } private void togglePlayToStop() { jButton_Play.setText("Stop"); jButton_Play.setIcon(IconSet.STOP_16X16); this.playingStatus = true; } private void toggleStopToPlay() { jButton_Play.setText("Play"); jButton_Play.setIcon(IconSet.PLAY_16X16); this.playingStatus = false; } private void toggleRecordToStop() { jButton_Record.setText("Stop"); jButton_Record.setIcon(IconSet.STOP_16X16); this.playingStatus = true; } private void toggleStopToRecord() { jButton_Record.setText("Record"); jButton_Record.setIcon(IconSet.REC_16X16); this.playingStatus = false; } protected void showMessage(String message, boolean warning) { jLabel_MessageBarIcon.setText(""); // No text, just an icon if (warning) { jLabel_MessageBarIcon.setIcon(IconSet.WARNING_16X16); jLabel_MessageBar.setForeground(Color.RED); // PRI4 Make darker red (more readable than default red) } else { jLabel_MessageBarIcon.setIcon(IconSet.INFO_16X16); jLabel_MessageBar.setForeground(Color.BLACK); } jLabel_MessageBar.setText(message); // Display the actual message next to the icon jLabel_MessageBar.setForeground(Color.BLACK); } private void setCheckBoxes(boolean flag) { this.jCheckBox_ContinueWithNext.setEnabled(flag); this.jCheckBox_PlayBackRec.setEnabled(flag); this.jCheckBox_PlayClosingBeep.setEnabled(flag); this.jCheckBox_PlaySynthesis.setEnabled(flag); } private void preparePlayback() { this.setCheckBoxes(false); if (this.recordingBlock) { // We're in a recording block so we want to use the Record button as the Stop button this.toggleRecordToStop(); // Disable the Play/Stop button so that user can't accidentally begin playback this.jButton_Play.setEnabled(false); jButton_Display.setEnabled(false); } else { // Disable the Record/Stop button so that user can't accidentally begin a recording this.jButton_Record.setEnabled(false); } } private void endPlayback() { if (!this.continuousMode) { // We're not in continuous mode, so return the Record button to normal if (this.recordingBlock) { // Record button was used as the Stop button toggleStopToRecord(); // Update button text (change from "Stop" to "Record") this.jButton_Play.setEnabled(true); // Re-enable the Play/Stop button jButton_Display.setEnabled(true); } else { // Play button was used as the Stop button toggleStopToPlay(); // Update button text (change from "Stop" to "Play") this.jButton_Record.setEnabled(true); // Re-enable the Record/Stop button } } // If we're in continuous mode then we want to leave these buttons as they are this.setCheckBoxes(true); } private String getClippingMessage(Recording rec) { String message; if ((rec.isAmpClipped) && (rec.isTempClipped)) { message = "Amplitude and temporal clipping detected."; } else if (rec.isAmpClipped) { message = "Amplitude clipping detected."; } else if (rec.isTempClipped) { message = "Temporal clipping detected. "; } else if (rec.isAmpWarning) { message = "Near amplitude clipping threshold"; } else { message = "No clipping detected."; } return message; } public class ClippingColorRenderer extends DefaultTableCellRenderer { public ClippingColorRenderer() { super(); setOpaque(true); // MUST do this for background to show up. } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (promptArray != null && promptArray.length >= row) { Prompt currentPrompt = promptArray[row]; if (currentPrompt != null) { Recording currentRecording = currentPrompt.getRecording(); if (currentRecording != null) { // Determine cell colour Color backgroundColor = Color.WHITE; // Reset first to white // If amplitude clipping or temporal clipping occurred, then cell background is pink // Note: Red is too harsh (too saturated) if ((currentRecording.isAmpClipped) || (currentRecording.isTempClipped)) { backgroundColor = Color.PINK; } // Otherwise if within the warning threshold, cell background is yellow else if (currentRecording.isAmpWarning) { backgroundColor = Color.YELLOW; } setBackground(backgroundColor); } } } return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton jButton_Display; private javax.swing.JButton jButton_Play; private javax.swing.JButton jButton_Record; private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem_AdminWindow; private javax.swing.JCheckBoxMenuItem jCheckBoxMenuItem_SpeakerWindow; private javax.swing.JCheckBox jCheckBox_ContinueWithNext; private javax.swing.JCheckBox jCheckBox_PlayBackRec; private javax.swing.JCheckBox jCheckBox_PlayClosingBeep; private javax.swing.JCheckBox jCheckBox_PlaySynthesis; private javax.swing.JLabel jLabel_MessageBar; private javax.swing.JLabel jLabel_MessageBarIcon; private javax.swing.JLabel jLabel_SessionStatus; private javax.swing.JMenuBar jMenuBar_AdminWindow; private javax.swing.JMenuItem jMenuItem_Exit; private javax.swing.JMenuItem jMenuItem_ImportText; private javax.swing.JMenuItem jMenuItem_Open; private javax.swing.JMenuItem jMenuItem_Options; private javax.swing.JMenuItem jMenu_About; private javax.swing.JMenu jMenu_File; private javax.swing.JMenu jMenu_Help; private javax.swing.JMenu jMenu_Tools; private javax.swing.JMenu jMenu_Window; private javax.swing.JPanel jPanel_AdminControls; private javax.swing.JPanel jPanel_SpeakerView; private javax.swing.JScrollPane jScrollPane_PromptSet; private javax.swing.JSeparator jSeparator_File; private javax.swing.JSeparator jSeparator_MessageBar; private javax.swing.JTextPane jTextPane_PromptDisplay; private javax.swing.JTextPane jTextPane_nextSentence; // End of variables declaration//GEN-END:variables }