diff --git a/resources/uk/co/majenko/audiobookrecorder/icons/processing.png b/resources/uk/co/majenko/audiobookrecorder/icons/processing.png new file mode 100644 index 0000000..fd50901 Binary files /dev/null and b/resources/uk/co/majenko/audiobookrecorder/icons/processing.png differ diff --git a/resources/uk/co/majenko/audiobookrecorder/icons/queued.png b/resources/uk/co/majenko/audiobookrecorder/icons/queued.png new file mode 100644 index 0000000..8409ec2 Binary files /dev/null and b/resources/uk/co/majenko/audiobookrecorder/icons/queued.png differ diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java index a22062d..9b2a2a2 100644 --- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java +++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java @@ -19,6 +19,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; import java.lang.reflect.Method; +import java.awt.FlowLayout; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Desktop; @@ -206,6 +207,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public static AudiobookRecorder window; public QueueprocessQueue = null; + public QueueMonitor queueMonitor = null; void buildToolbar(Container ob) { Debug.trace(); @@ -446,8 +448,11 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { Options.loadPreferences(); + queueMonitor = new QueueMonitor(processQueue); + for (int i = 0; i < Options.getInteger("process.threads"); i++) { - WorkerThread worker = new WorkerThread(processQueue); + WorkerThread worker = new WorkerThread(processQueue, queueMonitor); + queueMonitor.addThread(worker); worker.start(); } @@ -531,11 +536,12 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void actionPerformed(ActionEvent e) { Debug.trace(); if (selectedSentence != null) { - selectedSentence.autoTrimSampleFFT(); - sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); - sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); - postSentenceGap.setValue(selectedSentence.getPostGap()); - gainPercent.setValue((int)(selectedSentence.getGain() * 100d)); + queueJob(new SentenceJob(selectedSentence) { + public void run() { + sentence.autoTrimSampleFFT(); + updateWaveformMarkers(); + } + }); } } }); @@ -544,11 +550,12 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void actionPerformed(ActionEvent e) { Debug.trace(); if (selectedSentence != null) { - selectedSentence.autoTrimSamplePeak(); - sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); - sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); - postSentenceGap.setValue(selectedSentence.getPostGap()); - gainPercent.setValue((int)(selectedSentence.getGain() * 100d)); + queueJob(new SentenceJob(selectedSentence) { + public void run() { + sentence.autoTrimSamplePeak(); + updateWaveformMarkers(); + } + }); } } }); @@ -656,8 +663,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { doCutSplit.setEnabled(false); selectCutMode.setSelected(false); selectSplitMode.setSelected(false); - - bookTreeModel.reload(selectedSentence); + selectedSentence.reloadTree(); } }); controlsTop.add(locked); @@ -678,7 +684,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { selectedSentence.setAttentionFlag(false); } } - bookTreeModel.reload(selectedSentence); + selectedSentence.reloadTree(); } }); @@ -746,10 +752,12 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { centralPanel.add(sampleControl, BorderLayout.SOUTH); statusBar = new JPanel(); + statusBar.setLayout(new FlowLayout(FlowLayout.CENTER)); add(statusBar, BorderLayout.SOUTH); statusLabel = new JLabel("Noise floor: " + getNoiseFloorDB() + "dB"); statusBar.add(statusLabel); + statusBar.add(queueMonitor); buildToolbar(centralPanel); @@ -933,12 +941,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { Debug.trace(); if (ev.getPropertyName().equals("dividerLocation")) { if ((bookTreeModel != null) && (book != null)) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - Debug.trace(); - bookTreeModel.reload(book); - } - }); + Debug.trace(); + book.reloadTree(); } } } @@ -1195,9 +1199,11 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { Sentence snt = (Sentence)s.nextElement(); if (!snt.isLocked()) { if (snt.getId().equals(snt.getText())) { - Runnable r = snt.getRecognitionRunnable(); - snt.setQueued(); - queueJob(r); + queueJob(new SentenceJob(snt) { + public void run() { + sentence.doRecognition(); + } + }); } } } @@ -1230,7 +1236,11 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { JMenuObject o = (JMenuObject)e.getSource(); Sentence s = (Sentence)o.getObject(); if (!s.isLocked()) { - s.recognise(); + queueJob(new SentenceJob(s) { + public void run() { + sentence.doRecognition(); + } + }); } } }); @@ -1307,7 +1317,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { String type = (String)o.getObject2(); sent.setPostGapType(type); sent.setPostGap(Options.getInteger("catenation.post-sentence")); - bookTreeModel.reload(sent); + sent.reloadTree(); } }); setGapType.add(gapTypeSentence); @@ -1320,7 +1330,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { String type = (String)o.getObject2(); sent.setPostGapType(type); sent.setPostGap(Options.getInteger("catenation.short-sentence")); - bookTreeModel.reload(sent); + sent.reloadTree(); } }); setGapType.add(gapTypeContinuation); @@ -1333,7 +1343,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { String type = (String)o.getObject2(); sent.setPostGapType(type); sent.setPostGap(Options.getInteger("catenation.post-paragraph")); - bookTreeModel.reload(sent); + sent.reloadTree(); } }); setGapType.add(gapTypeParagraph); @@ -1346,7 +1356,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { String type = (String)o.getObject2(); sent.setPostGapType(type); sent.setPostGap(Options.getInteger("catenation.post-section")); - bookTreeModel.reload(sent); + sent.reloadTree(); } }); setGapType.add(gapTypeSection); @@ -1475,14 +1485,19 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void actionPerformed(ActionEvent e) { Debug.trace(); JMenuObject o = (JMenuObject)e.getSource(); - Chapter chap = (Chapter)o.getObject(); + Chapter c = (Chapter)o.getObject(); + for (Enumeration s = c.children(); s.hasMoreElements();) { + Sentence snt = (Sentence)s.nextElement(); + if (!snt.isProcessed()) { + queueJob(new SentenceJob(snt) { + public void run() { + sentence.autoTrimSampleFFT(); + updateWaveformMarkers(); + } + }); + } + } - ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName()); - - AutoTrimThread t = new AutoTrimThread(chap, ed, AutoTrimThread.Peak, AutoTrimThread.NewOnly); - Thread nt = new Thread(t); - nt.start(); - ed.setVisible(true); } }); @@ -1490,14 +1505,18 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void actionPerformed(ActionEvent e) { Debug.trace(); JMenuObject o = (JMenuObject)e.getSource(); - Chapter chap = (Chapter)o.getObject(); - - ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName()); - - AutoTrimThread t = new AutoTrimThread(chap, ed, AutoTrimThread.FFT, AutoTrimThread.NewOnly); - Thread nt = new Thread(t); - nt.start(); - ed.setVisible(true); + Chapter c = (Chapter)o.getObject(); + for (Enumeration s = c.children(); s.hasMoreElements();) { + Sentence snt = (Sentence)s.nextElement(); + if (!snt.isProcessed()) { + queueJob(new SentenceJob(snt) { + public void run() { + sentence.autoTrimSampleFFT(); + updateWaveformMarkers(); + } + }); + } + } } }); @@ -1505,14 +1524,16 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void actionPerformed(ActionEvent e) { Debug.trace(); JMenuObject o = (JMenuObject)e.getSource(); - Chapter chap = (Chapter)o.getObject(); - - ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName()); - - AutoTrimThread t = new AutoTrimThread(chap, ed, AutoTrimThread.Peak, AutoTrimThread.All); - Thread nt = new Thread(t); - nt.start(); - ed.setVisible(true); + Chapter c = (Chapter)o.getObject(); + for (Enumeration s = c.children(); s.hasMoreElements();) { + Sentence snt = (Sentence)s.nextElement(); + queueJob(new SentenceJob(snt) { + public void run() { + sentence.autoTrimSamplePeak(); + updateWaveformMarkers(); + } + }); + } } }); @@ -1520,14 +1541,16 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void actionPerformed(ActionEvent e) { Debug.trace(); JMenuObject o = (JMenuObject)e.getSource(); - Chapter chap = (Chapter)o.getObject(); - - ProgressDialog ed = new ProgressDialog("Auto-trimming " + chap.getName()); - - AutoTrimThread t = new AutoTrimThread(chap, ed, AutoTrimThread.FFT, AutoTrimThread.All); - Thread nt = new Thread(t); - nt.start(); - ed.setVisible(true); + Chapter c = (Chapter)o.getObject(); + for (Enumeration s = c.children(); s.hasMoreElements();) { + Sentence snt = (Sentence)s.nextElement(); + queueJob(new SentenceJob(snt) { + public void run() { + sentence.autoTrimSampleFFT(); + updateWaveformMarkers(); + } + }); + } } }); @@ -1600,7 +1623,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { for (Enumeration s = c.children(); s.hasMoreElements();) { Sentence snt = (Sentence)s.nextElement(); snt.setLocked(true); - bookTreeModel.reload(snt); + snt.reloadTree(); } } }); @@ -1613,7 +1636,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { for (Enumeration s = c.children(); s.hasMoreElements();) { Sentence snt = (Sentence)s.nextElement(); snt.setLocked(false); - bookTreeModel.reload(snt); + snt.reloadTree(); } } }); @@ -2073,7 +2096,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { if (recording == null) return; recording.stopRecording(); - bookTreeModel.reload(book); + book.reloadTree(); bookTree.expandPath(new TreePath(((DefaultMutableTreeNode)recording.getParent()).getPath())); bookTree.setSelectionPath(new TreePath(recording.getPath())); @@ -2188,8 +2211,12 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { bookTree.setEditable(true); bookTree.setUI(new CustomTreeUI(mainScroll)); - bookTree.setCellRenderer(new BookTreeRenderer()); - + try { + bookTree.setCellRenderer(new BookTreeRenderer()); + } catch (Exception ex) { + ex.printStackTrace(); + bookTree.setCellRenderer(new BookTreeRenderer()); + } InputMap im = bookTree.getInputMap(JComponent.WHEN_FOCUSED); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "startStopPlayback"); @@ -2283,7 +2310,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { } else { book.setIcon(Icons.book); } - bookTreeModel.reload(book); + book.reloadTree(); bookTree.expandPath(new TreePath(book.getPath())); @@ -2319,7 +2346,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { ImageIcon i = new ImageIcon(cf.getAbsolutePath()); Image ri = Utils.getScaledImage(i.getImage(), 22, 22); book.setIcon(new ImageIcon(ri)); - bookTreeModel.reload(book); + book.reloadTree(); } } catch (Exception e) { e.printStackTrace(); @@ -2719,55 +2746,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { } } - class AutoTrimThread implements Runnable { - ProgressDialog dialog; - Chapter chapter; - int type; - int scope; - - public final static int FFT = 0; - public final static int Peak = 1; - public final static int NewOnly = 0; - public final static int All = 1; - - public AutoTrimThread(Chapter c, ProgressDialog e, int t, int sc) { - super(); - Debug.trace(); - dialog = e; - chapter = c; - type = t; - scope = sc; - } - - @SuppressWarnings("unchecked") - public void run() { - Debug.trace(); - - int numKids = chapter.getChildCount(); - int kidCount = 0; - for (Enumeration s = chapter.children(); s.hasMoreElements();) { - kidCount++; - dialog.setProgress(kidCount * 2000 / numKids); - Sentence snt = (Sentence)s.nextElement(); - if (scope == NewOnly) { - if (snt.isProcessed()) continue; - } - switch (type) { - case FFT: - snt.autoTrimSampleFFT(); - break; - case Peak: - snt.autoTrimSamplePeak(); - break; - } - } - - dialog.closeDialog(); - } - } - - - class ExportThread implements Runnable { ProgressDialog exportDialog; Chapter chapter; @@ -3503,7 +3481,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { ImageIcon i = new ImageIcon(dest.getAbsolutePath()); Image ri = Utils.getScaledImage(i.getImage(), 22, 22); book.setIcon(new ImageIcon(ri)); - bookTreeModel.reload(book); + book.reloadTree(); } catch (Exception e) { e.printStackTrace(); @@ -3548,6 +3526,13 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { } } + synchronized public void updateWaveformMarkers() { + if (selectedSentence != null) { + sampleWaveform.setMarkers(selectedSentence.getStartOffset(), selectedSentence.getEndOffset()); + sampleWaveform.setAltMarkers(selectedSentence.getStartCrossing(), selectedSentence.getEndCrossing()); + } + } + public void loadEffects() { Debug.trace(); effects = new TreeMap(); @@ -4207,6 +4192,10 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { public void queueJob(Runnable r) { synchronized(processQueue) { processQueue.add(r); + if (r instanceof SentenceJob) { + SentenceJob sj = (SentenceJob)r; + sj.setQueued(); + } processQueue.notify(); } } diff --git a/src/uk/co/majenko/audiobookrecorder/Book.java b/src/uk/co/majenko/audiobookrecorder/Book.java index efa2081..cc1209a 100644 --- a/src/uk/co/majenko/audiobookrecorder/Book.java +++ b/src/uk/co/majenko/audiobookrecorder/Book.java @@ -8,6 +8,7 @@ import java.util.UUID; import java.util.Properties; import javax.sound.sampled.AudioFormat; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import javax.swing.ImageIcon; import javax.swing.tree.DefaultTreeModel; import javax.xml.parsers.DocumentBuilderFactory; @@ -217,7 +218,7 @@ public class Book extends BookTreeNode { oldDir.renameTo(newDir); name = newName; AudiobookRecorder.window.saveBookStructure(); - AudiobookRecorder.window.bookTreeModel.reload(this); + reloadTree(); Options.set("path.last-book", name); Options.savePreferences(); AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); @@ -447,4 +448,12 @@ public class Book extends BookTreeNode { public void setLocation(File l) { location = l; } + + public void reloadTree() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + AudiobookRecorder.window.bookTreeModel.reload(Book.this); + } + }); + } } diff --git a/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java b/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java index 2aaf378..ddc6c66 100644 --- a/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java +++ b/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java @@ -2,9 +2,11 @@ package uk.co.majenko.audiobookrecorder; import java.awt.Component; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import javax.swing.SwingConstants; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTree; @@ -84,7 +86,8 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer { } - JLabel time = new JLabel(Utils.secToTime(s.getLength(), "mm:ss.SSS") + " "); + JLabel time = new JLabelFixedWidth(75, " " + Utils.secToTime(s.getLength(), "ss.SSS") + " "); + time.setHorizontalAlignment(SwingConstants.RIGHT); ctx.gridx = 0; ctx.gridy = 0; @@ -93,17 +96,18 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer { ctx.anchor = GridBagConstraints.LINE_START; p.add(ret, ctx); - if (s.isDetecting()) { - JLabel eff = new JLabel(" recognising... "); + if (s.isProcessing()) { + JLabel eff = new JLabel(); + eff.setIcon(Icons.processing); ctx.weightx = 0.0d; ctx.gridx = 1; p.add(eff); } else if (s.isQueued()) { - JLabel eff = new JLabel(" queued "); + JLabel eff = new JLabel(); + eff.setIcon(Icons.queued); ctx.weightx = 0.0d; ctx.gridx = 1; p.add(eff); - } else if (s.isQueued()) { } String effectChain = s.getEffectChain(); @@ -121,7 +125,8 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer { ctx.gridx = 3; ctx.anchor = GridBagConstraints.LINE_END; int peak = s.getPeakDB(); - JLabel peakLabel = new JLabel(peak + "dB "); + JLabel peakLabel = new JLabelFixedWidth(50, peak + "dB "); + peakLabel.setHorizontalAlignment(SwingConstants.RIGHT); if (peak > 0) { peakLabel.setForeground(new Color(0xCC, 0x00, 0x00)); } diff --git a/src/uk/co/majenko/audiobookrecorder/Icons.java b/src/uk/co/majenko/audiobookrecorder/Icons.java index 6205856..c258770 100644 --- a/src/uk/co/majenko/audiobookrecorder/Icons.java +++ b/src/uk/co/majenko/audiobookrecorder/Icons.java @@ -40,4 +40,6 @@ public class Icons { static public final ImageIcon disable = new ImageIcon(Icons.class.getResource("icons/disable-effects.png")); static public final ImageIcon manuscript = new ImageIcon(Icons.class.getResource("icons/manuscript.png")); static public final ImageIcon tooltip = new ImageIcon(Icons.class.getResource("icons/tooltip.png")); + static public final ImageIcon queued = new ImageIcon(Icons.class.getResource("icons/queued.png")); + static public final ImageIcon processing = new ImageIcon(Icons.class.getResource("icons/processing.png")); } diff --git a/src/uk/co/majenko/audiobookrecorder/JLabelFixedWidth.java b/src/uk/co/majenko/audiobookrecorder/JLabelFixedWidth.java new file mode 100644 index 0000000..bbf962b --- /dev/null +++ b/src/uk/co/majenko/audiobookrecorder/JLabelFixedWidth.java @@ -0,0 +1,38 @@ +package uk.co.majenko.audiobookrecorder; + +import javax.swing.JLabel; +import java.awt.Dimension; + +public class JLabelFixedWidth extends JLabel { + int width = 0; + int height = 0; + Dimension size; + public JLabelFixedWidth(int w, String txt) { + super(txt); + JLabel t = new JLabel(txt); + size = t.getPreferredSize(); + size.width = w; + } + + public JLabelFixedWidth(int w) { + super(); + JLabel t = new JLabel("nothing"); + size = t.getPreferredSize(); + size.width = w; + } + + @Override + public Dimension getPreferredSize() { + return size; + } + + @Override + public Dimension getMaximumSize() { + return size; + } + + @Override + public Dimension getMinimumSize() { + return size; + } +} diff --git a/src/uk/co/majenko/audiobookrecorder/QueueMonitor.java b/src/uk/co/majenko/audiobookrecorder/QueueMonitor.java new file mode 100644 index 0000000..ebad589 --- /dev/null +++ b/src/uk/co/majenko/audiobookrecorder/QueueMonitor.java @@ -0,0 +1,71 @@ +package uk.co.majenko.audiobookrecorder; + +import javax.swing.JPanel; +import java.util.ArrayList; +import java.util.Queue; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Dimension; +import java.awt.Color; + +public class QueueMonitor extends JPanel { + + ArrayList threadList = new ArrayList(); + Queue queue; + + public QueueMonitor(Queue q) { + super(); + queue = q; + } + + public void addThread(WorkerThread t) { + threadList.add(t); + } + + public void purgeQueue() { + synchronized (queue) { + queue.clear(); + repaint(); + } + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(100 + (24 * threadList.size()), 24); + } + + @Override + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + @Override + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + @Override + public void paintComponent(Graphics g) { + Rectangle size = g.getClipBounds(); + g.setColor(getBackground()); + g.fillRect(0, 0, size.width - 1, size.height - 1); + g.setColor(new Color(10, 10, 10)); + g.drawRect(0, 0, size.width - 1, size.height - 1); + g.setFont(getFont()); + + for (int i = 0; i < threadList.size(); i++) { + WorkerThread t = threadList.get(i); + if (t.isRunning()) { + g.setColor(new Color(50, 200, 0)); + } else { + g.setColor(new Color(80, 0, 0)); + } + g.fillOval(i * 24 + 4, 4, 22 - 8, 22 - 8); + } + + g.setColor(getForeground()); + g.drawString("Queued: " + queue.size(), threadList.size() * 24 + 4, 16); + } + +} + diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java index 05d472a..f10d928 100644 --- a/src/uk/co/majenko/audiobookrecorder/Sentence.java +++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java @@ -33,6 +33,7 @@ import java.io.FileInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.AudioFileFormat; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import java.io.BufferedReader; import java.io.InputStream; import java.util.UUID; @@ -65,8 +66,11 @@ public class Sentence extends BookTreeNode implements Cacheable { boolean attention = false; boolean processed = false; boolean isDetected = false; - boolean detecting = false; - boolean queued = false; + + int state = IDLE; + static final int IDLE = 0; + static final int QUEUED = 1; + static final int PROCESSING = 2; String effectChain = null; @@ -706,8 +710,6 @@ public class Sentence extends BookTreeNode implements Cacheable { public void doRecognition() { Debug.trace(); - detecting = true; - queued = false; try { reloadTree(); @@ -727,12 +729,10 @@ public class Sentence extends BookTreeNode implements Cacheable { setText(res); isDetected = true; - detecting = false; reloadTree(); } catch (Exception e) { e.printStackTrace(); } - detecting = false; } public void recognise() { @@ -1670,9 +1670,11 @@ public class Sentence extends BookTreeNode implements Cacheable { Debug.trace(); if (id.equals("room-noise")) return; if (getParent() == null) return; - synchronized (AudiobookRecorder.window.bookTreeModel) { - AudiobookRecorder.window.bookTreeModel.reload(this); - } + SwingUtilities.invokeLater(new Runnable() { + public void run() { + AudiobookRecorder.window.bookTreeModel.reload(Sentence.this); + } + }); } public double getPeak() { @@ -1707,20 +1709,31 @@ public class Sentence extends BookTreeNode implements Cacheable { return (int)db; } - public boolean isDetecting() { - return detecting; - } - public boolean beenDetected() { return isDetected; } + public boolean isProcessing() { + return state == PROCESSING; + } + public boolean isQueued() { - return queued; + return state == QUEUED; + } + + public void setProcessing() { + state = PROCESSING; + reloadTree(); } public void setQueued() { - queued = true; + state = QUEUED; + reloadTree(); + } + + public void setDequeued() { + state = IDLE; + reloadTree(); } } diff --git a/src/uk/co/majenko/audiobookrecorder/SentenceJob.java b/src/uk/co/majenko/audiobookrecorder/SentenceJob.java new file mode 100644 index 0000000..fd65833 --- /dev/null +++ b/src/uk/co/majenko/audiobookrecorder/SentenceJob.java @@ -0,0 +1,25 @@ +package uk.co.majenko.audiobookrecorder; + +import java.lang.Runnable; + +public abstract class SentenceJob implements Runnable { + protected Sentence sentence; + + public SentenceJob(Sentence s) { + sentence = s; + } + + public void setQueued() { + sentence.setQueued(); + } + + public void setDequeued() { + sentence.setDequeued(); + } + + public void setProcessing() { + sentence.setProcessing(); + } + + public abstract void run(); +} diff --git a/src/uk/co/majenko/audiobookrecorder/WorkerThread.java b/src/uk/co/majenko/audiobookrecorder/WorkerThread.java index ac51b95..30b6186 100644 --- a/src/uk/co/majenko/audiobookrecorder/WorkerThread.java +++ b/src/uk/co/majenko/audiobookrecorder/WorkerThread.java @@ -5,9 +5,13 @@ import java.util.Queue; public class WorkerThread extends Thread { private static int instance = 0; private final Queue queue; + private final QueueMonitor monitor; + + private boolean running = false; - public WorkerThread(Queue queue) { + public WorkerThread(Queue queue, QueueMonitor mon) { this.queue = queue; + monitor = mon; setName("Worker Thread " + (instance++)); } @@ -30,8 +34,19 @@ public class WorkerThread extends Thread { work = queue.remove(); } - // Process the work item + running = true; + monitor.repaint(); + if (work instanceof SentenceJob) { + SentenceJob sj = (SentenceJob)work; + sj.setProcessing(); + } work.run(); + if (work instanceof SentenceJob) { + SentenceJob sj = (SentenceJob)work; + sj.setDequeued(); + } + running = false; + monitor.repaint(); } catch ( InterruptedException ie ) { ie.printStackTrace(); @@ -40,4 +55,8 @@ public class WorkerThread extends Thread { } Debug.d(getName(), "died"); } + + public boolean isRunning() { + return running; + } }