Implemented multiple open books
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -3,13 +3,14 @@ package uk.co.majenko.audiobookrecorder;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.awt.Image;
|
||||||
import javax.sound.sampled.AudioFormat;
|
import javax.sound.sampled.AudioFormat;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -50,26 +51,27 @@ public class Book extends BookTreeNode {
|
|||||||
int resolution;
|
int resolution;
|
||||||
String notes = null;
|
String notes = null;
|
||||||
ImageIcon icon;
|
ImageIcon icon;
|
||||||
Properties prefs;
|
|
||||||
File location;
|
File location;
|
||||||
Random rng = new Random();
|
Random rng = new Random();
|
||||||
TreeMap<String, EffectGroup> effects;
|
TreeMap<String, EffectGroup> effects;
|
||||||
|
|
||||||
public Book(Properties p, String bookname) {
|
public Book(String bookname) {
|
||||||
super(bookname);
|
super(bookname);
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
prefs = p;
|
|
||||||
name = bookname;
|
name = bookname;
|
||||||
|
location = new File(Options.get("path.storage"), sanitize(name));
|
||||||
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
||||||
|
setIcon(Icons.book);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
public Book(Element root) {
|
public Book(Element root) {
|
||||||
super(getTextNode(root, "title"));
|
super(getTextNode(root, "title"));
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
name = getTextNode(root, "title");
|
name = getTextNode(root, "title");
|
||||||
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
|
||||||
|
setIcon(Icons.book);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
public Book(File inputFile) throws SAXException, IOException, ParserConfigurationException {
|
public Book(File inputFile) throws SAXException, IOException, ParserConfigurationException {
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
Debug.d("Loading book from", inputFile.getCanonicalPath());
|
Debug.d("Loading book from", inputFile.getCanonicalPath());
|
||||||
@@ -103,13 +105,27 @@ public class Book extends BookTreeNode {
|
|||||||
|
|
||||||
loadEffects();
|
loadEffects();
|
||||||
|
|
||||||
Element chapters = getNode(root, "chapters");
|
File cf = new File(location, "coverart.png");
|
||||||
|
if (!cf.exists()) {
|
||||||
|
cf = new File(location, "coverart.jpg");
|
||||||
|
if (!cf.exists()) {
|
||||||
|
cf = new File(location, "coverart.gif");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NodeList chapterList = chapters.getElementsByTagName("chapter");
|
if (cf.exists()) {
|
||||||
|
ImageIcon i = new ImageIcon(cf.getAbsolutePath());
|
||||||
|
Image ri = Utils.getScaledImage(i.getImage(), 22, 22);
|
||||||
|
setIcon(new ImageIcon(ri));
|
||||||
|
} else {
|
||||||
|
setIcon(Icons.book);
|
||||||
|
}
|
||||||
|
|
||||||
roomNoise = new Sentence("room-noise", "Room Noise");
|
roomNoise = new Sentence("room-noise", "Room Noise");
|
||||||
roomNoise.setParentBook(this);
|
roomNoise.setParentBook(this);
|
||||||
|
|
||||||
|
Element chapters = getNode(root, "chapters");
|
||||||
|
NodeList chapterList = chapters.getElementsByTagName("chapter");
|
||||||
for (int i = 0; i < chapterList.getLength(); i++) {
|
for (int i = 0; i < chapterList.getLength(); i++) {
|
||||||
Element chapterElement = (Element)chapterList.item(i);
|
Element chapterElement = (Element)chapterList.item(i);
|
||||||
Chapter newChapter = new Chapter(chapterElement);
|
Chapter newChapter = new Chapter(chapterElement);
|
||||||
@@ -234,7 +250,9 @@ public class Book extends BookTreeNode {
|
|||||||
public Chapter addChapter() {
|
public Chapter addChapter() {
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
String uuid = UUID.randomUUID().toString();
|
String uuid = UUID.randomUUID().toString();
|
||||||
return new Chapter(uuid, uuid);
|
Chapter c = new Chapter(uuid, uuid);
|
||||||
|
c.setParentBook(this);
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -274,7 +292,11 @@ public class Book extends BookTreeNode {
|
|||||||
if (oldDir.exists() && oldDir.isDirectory()) {
|
if (oldDir.exists() && oldDir.isDirectory()) {
|
||||||
oldDir.renameTo(newDir);
|
oldDir.renameTo(newDir);
|
||||||
name = newName;
|
name = newName;
|
||||||
AudiobookRecorder.window.saveBookStructure();
|
try {
|
||||||
|
save();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
reloadTree();
|
reloadTree();
|
||||||
Options.set("path.last-book", name);
|
Options.set("path.last-book", name);
|
||||||
Options.savePreferences();
|
Options.savePreferences();
|
||||||
@@ -287,20 +309,6 @@ public class Book extends BookTreeNode {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void renumberChapters() {
|
|
||||||
Debug.trace();
|
|
||||||
int id = 1;
|
|
||||||
|
|
||||||
for (Enumeration c = children(); c.hasMoreElements();) {
|
|
||||||
Chapter chp = (Chapter)c.nextElement();
|
|
||||||
if (Utils.s2i(chp.getId()) > 0) {
|
|
||||||
chp.setId(String.format("%04d", id));
|
|
||||||
id++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSampleRate() { Debug.trace(); return sampleRate; }
|
public int getSampleRate() { Debug.trace(); return sampleRate; }
|
||||||
public void setSampleRate(int sr) { Debug.trace(); sampleRate = sr; }
|
public void setSampleRate(int sr) { Debug.trace(); sampleRate = sr; }
|
||||||
public int getChannels() { Debug.trace(); return channels; }
|
public int getChannels() { Debug.trace(); return channels; }
|
||||||
@@ -313,32 +321,8 @@ public class Book extends BookTreeNode {
|
|||||||
return new AudioFormat(getSampleRate(), getResolution(), getChannels(), true, false);
|
return new AudioFormat(getSampleRate(), getResolution(), getChannels(), true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String get(String key) {
|
|
||||||
Debug.trace();
|
|
||||||
if (prefs.getProperty(key) == null) { return Options.get(key); }
|
|
||||||
return prefs.getProperty(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getInteger(String key) {
|
|
||||||
Debug.trace();
|
|
||||||
if (prefs.getProperty(key) == null) { return Options.getInteger(key); }
|
|
||||||
return Utils.s2i(prefs.getProperty(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(String key, String value) {
|
|
||||||
Debug.trace();
|
|
||||||
prefs.setProperty(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(String key, Integer value) {
|
|
||||||
Debug.trace();
|
|
||||||
prefs.setProperty(key, "" + value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getBookFolder() {
|
public File getBookFolder() {
|
||||||
Debug.trace();
|
return location;
|
||||||
File dir = new File(Options.get("path.storage"), name);
|
|
||||||
return dir;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<String> getUsedEffects() {
|
public ArrayList<String> getUsedEffects() {
|
||||||
@@ -486,15 +470,20 @@ public class Book extends BookTreeNode {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSelect() {
|
public void onSelect(BookTreeNode target) {
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
|
AudiobookRecorder.setSelectedBook(this);
|
||||||
|
if (target == this) {
|
||||||
|
AudiobookRecorder.setSelectedChapter(null);
|
||||||
|
AudiobookRecorder.setSelectedSentence(null);
|
||||||
|
}
|
||||||
AudiobookRecorder.window.setBookNotes(notes);
|
AudiobookRecorder.window.setBookNotes(notes);
|
||||||
AudiobookRecorder.window.noiseFloorLabel.setNoiseFloor(getNoiseFloorDB());
|
AudiobookRecorder.window.noiseFloorLabel.setNoiseFloor(getNoiseFloorDB());
|
||||||
// AudiobookRecorder.window.updateEffectChains(effects);
|
// AudiobookRecorder.window.updateEffectChains(effects);
|
||||||
TreeNode p = getParent();
|
TreeNode p = getParent();
|
||||||
if (p instanceof BookTreeNode) {
|
if (p instanceof BookTreeNode) {
|
||||||
BookTreeNode btn = (BookTreeNode)p;
|
BookTreeNode btn = (BookTreeNode)p;
|
||||||
btn.onSelect();
|
btn.onSelect(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,4 +652,26 @@ public class Book extends BookTreeNode {
|
|||||||
StreamResult result = new StreamResult(xml);
|
StreamResult result = new StreamResult(xml);
|
||||||
transformer.transform(source, result);
|
transformer.transform(source, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getBookFile() {
|
||||||
|
return new File(location, "audiobook.abx");
|
||||||
|
}
|
||||||
|
|
||||||
|
final static int[] illegalChars = {34, 60, 62, 124, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 58, 42, 63, 92, 47};
|
||||||
|
|
||||||
|
static {
|
||||||
|
Arrays.sort(illegalChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sanitize(String badFileName) {
|
||||||
|
StringBuilder cleanName = new StringBuilder();
|
||||||
|
int len = badFileName.codePointCount(0, badFileName.length());
|
||||||
|
for (int i=0; i<len; i++) {
|
||||||
|
int c = badFileName.codePointAt(i);
|
||||||
|
if (Arrays.binarySearch(illegalChars, c) < 0) {
|
||||||
|
cleanName.appendCodePoint(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cleanName.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public abstract class BookTreeNode extends DefaultMutableTreeNode {
|
|||||||
public abstract void setNotes(String t);
|
public abstract void setNotes(String t);
|
||||||
public abstract String getNotes();
|
public abstract String getNotes();
|
||||||
|
|
||||||
public abstract void onSelect();
|
public abstract void onSelect(BookTreeNode target);
|
||||||
public abstract Book getBook();
|
public abstract Book getBook();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -369,13 +369,17 @@ public class Chapter extends BookTreeNode {
|
|||||||
notes = t;
|
notes = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSelect() {
|
public void onSelect(BookTreeNode target) {
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
|
AudiobookRecorder.setSelectedChapter(this);
|
||||||
|
if (target == this) {
|
||||||
|
AudiobookRecorder.setSelectedSentence(null);
|
||||||
|
}
|
||||||
AudiobookRecorder.window.setChapterNotes(notes);
|
AudiobookRecorder.window.setChapterNotes(notes);
|
||||||
TreeNode p = getParent();
|
TreeNode p = getParent();
|
||||||
if (p instanceof BookTreeNode) {
|
if (p instanceof BookTreeNode) {
|
||||||
BookTreeNode btn = (BookTreeNode)p;
|
BookTreeNode btn = (BookTreeNode)p;
|
||||||
btn.onSelect();
|
btn.onSelect(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class MainToolBar extends JToolBar {
|
|||||||
|
|
||||||
saveBook = new JButtonSpacePlay(Icons.save, "Save Book", new ActionListener() {
|
saveBook = new JButtonSpacePlay(Icons.save, "Save Book", new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
root.saveBookStructure();
|
root.saveAllBooks();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(saveBook);
|
add(saveBook);
|
||||||
@@ -65,7 +65,7 @@ public class MainToolBar extends JToolBar {
|
|||||||
|
|
||||||
recordRoomNoise = new JButtonSpacePlay(Icons.recordRoom, "Record Room Noise", new ActionListener() {
|
recordRoomNoise = new JButtonSpacePlay(Icons.recordRoom, "Record Room Noise", new ActionListener() {
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
root.book.recordRoomNoise();
|
root.getBook().recordRoomNoise();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
add(recordRoomNoise);
|
add(recordRoomNoise);
|
||||||
|
|||||||
@@ -224,12 +224,28 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
|||||||
if (text == null) text = id;
|
if (text == null) text = id;
|
||||||
if (text.equals("")) text = id;
|
if (text.equals("")) text = id;
|
||||||
|
|
||||||
// if (id.equals("room-noise")) return;
|
if (id.equals("room-noise")) return;
|
||||||
|
|
||||||
|
if (startOffset >= sampleSize) startOffset = 0;
|
||||||
|
if (endOffset >= sampleSize) endOffset = sampleSize - 1;
|
||||||
|
if (crossStartOffset >= sampleSize) crossStartOffset = 0;
|
||||||
|
if (crossEndOffset >= sampleSize) crossEndOffset = sampleSize - 1;
|
||||||
|
|
||||||
|
if (crossStartOffset == -1) {
|
||||||
|
crossStartOffset = startOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crossEndOffset == -1) {
|
||||||
|
crossEndOffset = endOffset;
|
||||||
|
}
|
||||||
// if ((crossStartOffset == -1) || (crossEndOffset == -1)) {
|
// if ((crossStartOffset == -1) || (crossEndOffset == -1)) {
|
||||||
// updateCrossings();
|
// updateCrossings();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// if (runtime <= 0.01d) getLength();
|
// if (runtime <= 0.01d) getLength();
|
||||||
|
if (runtime <= 0.001d) {
|
||||||
|
runtime = crossEndOffset - crossStartOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean startRecording() {
|
public boolean startRecording() {
|
||||||
@@ -817,6 +833,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
|||||||
public Sentence cloneSentence() throws IOException {
|
public Sentence cloneSentence() throws IOException {
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
Sentence sentence = new Sentence();
|
Sentence sentence = new Sentence();
|
||||||
|
sentence.setParentBook(getBook());
|
||||||
sentence.setPostGap(getPostGap());
|
sentence.setPostGap(getPostGap());
|
||||||
if (!id.equals(text)) {
|
if (!id.equals(text)) {
|
||||||
sentence.setText(text);
|
sentence.setText(text);
|
||||||
@@ -966,6 +983,9 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
|||||||
Debug.trace();
|
Debug.trace();
|
||||||
ExternalEditor ed = new ExternalEditor(this);
|
ExternalEditor ed = new ExternalEditor(this);
|
||||||
ed.run();
|
ed.run();
|
||||||
|
CacheManager.removeFromCache(this);
|
||||||
|
runtime = -1;
|
||||||
|
sampleSize = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void backup() throws IOException {
|
public void backup() throws IOException {
|
||||||
@@ -1009,6 +1029,10 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
|||||||
if (command == null) return;
|
if (command == null) return;
|
||||||
if (command.equals("")) return;
|
if (command.equals("")) return;
|
||||||
|
|
||||||
|
Debug.d("Starting size:", sampleSize);
|
||||||
|
Debug.d("Start offset:", startOffset, crossStartOffset);
|
||||||
|
Debug.d("End offset:", endOffset, crossEndOffset);
|
||||||
|
|
||||||
String[] parts = command.split("::");
|
String[] parts = command.split("::");
|
||||||
|
|
||||||
ArrayList<String> args = new ArrayList<String>();
|
ArrayList<String> args = new ArrayList<String>();
|
||||||
@@ -1051,6 +1075,17 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CacheManager.removeFromCache(Sentence.this);
|
CacheManager.removeFromCache(Sentence.this);
|
||||||
|
runtime = -1;
|
||||||
|
sampleSize = -1;
|
||||||
|
loadFile();
|
||||||
|
Debug.d("Ending size:", sampleSize);
|
||||||
|
if (startOffset >= sampleSize) startOffset = 0;
|
||||||
|
if (endOffset >= sampleSize) endOffset = sampleSize - 1;
|
||||||
|
crossStartOffset = -1;
|
||||||
|
crossEndOffset = -1;
|
||||||
|
updateCrossings();
|
||||||
|
Debug.d("Start offset:", startOffset, crossStartOffset);
|
||||||
|
Debug.d("End offset:", endOffset, crossEndOffset);
|
||||||
AudiobookRecorder.window.updateWaveform(true);
|
AudiobookRecorder.window.updateWaveform(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1627,13 +1662,14 @@ public class Sentence extends BookTreeNode implements Cacheable {
|
|||||||
return notes;
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSelect() {
|
public void onSelect(BookTreeNode target) {
|
||||||
Debug.trace();
|
Debug.trace();
|
||||||
|
AudiobookRecorder.setSelectedSentence(this);
|
||||||
AudiobookRecorder.window.setSentenceNotes(notes);
|
AudiobookRecorder.window.setSentenceNotes(notes);
|
||||||
TreeNode p = getParent();
|
TreeNode p = getParent();
|
||||||
if (p instanceof BookTreeNode) {
|
if (p instanceof BookTreeNode) {
|
||||||
BookTreeNode btn = (BookTreeNode)p;
|
BookTreeNode btn = (BookTreeNode)p;
|
||||||
btn.onSelect();
|
btn.onSelect(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user