diff --git a/ExampleExportFilters/librivox.abprof b/ExampleExportFilters/librivox.abprof
new file mode 100644
index 0000000..88a51a2
--- /dev/null
+++ b/ExampleExportFilters/librivox.abprof
@@ -0,0 +1,21 @@
+
+ librivox
+ LibriVox.org
+
+ 128000
+ 1
+ 44100
+ {chapter.name:lower}_{book.author.short:lower}_{narrator.initials:lower}_{file.bitrate.kb}kb
+
+
+ 500
+ 5000
+ 400
+ 100
+ 1000
+ 1200
+
+
+
diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java
index 448f787..140573a 100644
--- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java
+++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java
@@ -6,6 +6,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.ArrayDeque;
import java.util.Enumeration;
import java.util.Properties;
@@ -119,6 +120,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public static CommandLine CLI = new CommandLine();
+ public static HashMap exportProfiles = new HashMap();
+
MainToolBar toolBar;
JMenuBar menuBar;
@@ -357,6 +360,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Options.loadPreferences();
+ loadExportProfiles();
+
queueMonitor = new QueueMonitor(processQueue);
for (int i = 0; i < Options.getInteger("process.threads"); i++) {
@@ -1079,7 +1084,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public void createNewBook() {
Debug.trace();
- BookInfoPanel info = new BookInfoPanel("", "", "", "", "", "");
+ BookInfoPanel info = new BookInfoPanel("", "", "", "", "", "", "", "", "");
int r = JOptionPane.showConfirmDialog(this, info, "New Book", JOptionPane.OK_CANCEL_OPTION);
if (r != JOptionPane.OK_OPTION) return;
@@ -1634,10 +1639,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
}
});
- JMenu exportChapter = new JMenu("Export chapter...");
-
-
- JMenuObject exportChapterACX = new JMenuObject("For ACX", c, new ActionListener() {
+ JMenuObject exportChapter = new JMenuObject("Export Chapter", c, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject o = (JMenuObject)e.getSource();
@@ -1645,37 +1647,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
ProgressDialog ed = new ProgressDialog("Exporting " + chap.getName());
- ExportThread t = new ExportThread(chap, ed, "{book.title} - {chapter.number}");
- Thread nt = new Thread(t);
- nt.start();
- ed.setVisible(true);
- }
- });
-
- JMenuObject exportChapterABU = new JMenuObject("For Audiobooks Unleashed", c, new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Debug.trace();
- JMenuObject o = (JMenuObject)e.getSource();
- Chapter chap = (Chapter)o.getObject();
-
- ProgressDialog ed = new ProgressDialog("Exporting " + chap.getName());
-
- ExportThread t = new ExportThread(chap, ed, "{book.isbn}_{chapter.number}");
- Thread nt = new Thread(t);
- nt.start();
- ed.setVisible(true);
- }
- });
-
- JMenuObject exportChapterLibri = new JMenuObject("For LibriVox.org", c, new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Debug.trace();
- JMenuObject o = (JMenuObject)e.getSource();
- Chapter chap = (Chapter)o.getObject();
-
- ProgressDialog ed = new ProgressDialog("Exporting " + chap.getName());
-
- ExportThread t = new ExportThread(chap, ed, "{chapter.name:lower}_{book.author:lower}_{narrator.initials:lower}_{file.bitrate.kb}kb");
+ ExportThread t = new ExportThread(chap, ed);
Thread nt = new Thread(t);
nt.start();
ed.setVisible(true);
@@ -1785,9 +1757,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
menu.addSeparator();
menu.add(importWav);
menu.add(exportChapter);
- exportChapter.add(exportChapterACX);
- exportChapter.add(exportChapterABU);
- exportChapter.add(exportChapterLibri);
menu.addSeparator();
menu.add(deleteChapter);
menu.addSeparator();
@@ -1841,35 +1810,16 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
menu.addSeparator();
- JMenu exportAll = new JMenu("Export All Audio...");
- menu.add(exportAll);
-
- exportAll.add(new JMenuObject("For ACX", book, new ActionListener() {
+ JMenuObject exportAll = new JMenuObject("Export Book", book, new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
JMenuObject src = (JMenuObject)(e.getSource());
Book thisBook = (Book)(src.getObject());
- exportAudio(thisBook, "{book.title} - {chapter.number}");
+ exportAudio(thisBook);
}
- }));
+ });
- exportAll.add(new JMenuObject("For Audiobooks Unleashed", book, new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Debug.trace();
- JMenuObject src = (JMenuObject)(e.getSource());
- Book thisBook = (Book)(src.getObject());
- exportAudio(thisBook, "{book.isbn}_{chapter.number}");
- }
- }));
-
- exportAll.add(new JMenuObject("For LibriVox.org", book, new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- Debug.trace();
- JMenuObject src = (JMenuObject)(e.getSource());
- Book thisBook = (Book)(src.getObject());
- exportAudio(thisBook, "{chapter.name:lower}_{book.author:lower}_{narrator.initials:lower}_{file.bitrate.kb}kb");
- }
- }));
+ menu.add(exportAll);
JMenu visitACX = new JMenu("Visit ACX");
@@ -2335,8 +2285,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public Chapter convertChapter(String name, String id, Properties data) {
Chapter c = new Chapter(id, data.getProperty("chapter." + name + ".name"));
- c.setPostGap(Utils.s2i(data.getProperty("chapter." + name + ".post-gap")));
- c.setPreGap(Utils.s2i(data.getProperty("chapter." + name + ".pre-gap")));
for (int i = 0; i < 100000000; i++) {
String sid = data.getProperty(String.format("chapter." + name + ".sentence.%08d.id", i));
@@ -2517,14 +2465,12 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
class ExportThread implements Runnable {
ProgressDialog exportDialog;
Chapter chapter;
- String format;
- public ExportThread(Chapter c, ProgressDialog e, String f) {
+ public ExportThread(Chapter c, ProgressDialog e) {
super();
Debug.trace();
exportDialog = e;
chapter = c;
- format = f;
}
@SuppressWarnings("unchecked")
@@ -2532,7 +2478,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
Debug.trace();
try {
- chapter.exportChapter(exportDialog, format);
+ chapter.exportChapter(exportDialog);
} catch (Exception e) {
e.printStackTrace();
}
@@ -2542,7 +2488,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
}
@SuppressWarnings("unchecked")
- public void exportAudio(Book book, String format) {
+ public void exportAudio(Book book) {
Debug.trace();
for (Enumeration o = book.children(); o.hasMoreElements();) {
@@ -2550,7 +2496,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
if (c.getChildCount() == 0) continue;
ProgressDialog ed = new ProgressDialog("Exporting " + c.getName());
- ExportThread t = new ExportThread(c, ed, format);
+ ExportThread t = new ExportThread(c, ed);
Thread nt = new Thread(t);
nt.start();
ed.setVisible(true);
@@ -3601,13 +3547,21 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
public void editBookInfo(Book book) {
JTabbedPane tabs = new JTabbedPane();
+ String epc = "";
+ if (book.getExportProfile() != null) {
+ epc = book.getExportProfile().getCode();
+ }
+
BookInfoPanel info = new BookInfoPanel(
book.getName(),
+ book.getShortTitle(),
book.getAuthor(),
+ book.getShortAuthor(),
book.getGenre(),
book.getComment(),
book.getACX(),
- book.getISBN()
+ book.getISBN(),
+ epc
);
tabs.add("Data", info);
@@ -3644,7 +3598,9 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
if (r != JOptionPane.OK_OPTION) return;
String tit = info.getTitle();
+ String stit = info.getShortTitle();
String aut = info.getAuthor();
+ String saut = info.getShortAuthor();
String gen = info.getGenre();
String com = info.getComment();
String acx = info.getACX();
@@ -3656,11 +3612,14 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
book.setDefaultEffect(de.getKey());
}
book.setTitle(tit);
+ book.setShortTitle(stit);
book.setAuthor(aut);
+ book.setShortAuthor(saut);
book.setGenre(gen);
book.setComment(com);
book.setACX(acx);
book.setISBN(isbn);
+ book.setExportProfile(info.getExportProfile());
// if (!(book().getName().equals(tit))) {
// book().renameBook(tit);
// }
@@ -3708,4 +3667,21 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
ex.printStackTrace();
}
}
+
+ public void loadExportProfiles() {
+ exportProfiles.clear();
+ ExportProfile dp = new ExportProfile();
+ exportProfiles.put(dp.getCode(), dp);
+ File system = new File(Options.get("path.storage"), "system");
+ if (system.exists() && system.isDirectory()) {
+ File profiles = new File(system, "profiles");
+ for (File f : profiles.listFiles()) {
+ if (f.getName().endsWith(".abprof")) {
+ ExportProfile p = new ExportProfile(f);
+ exportProfiles.put(p.getCode(), p);
+ }
+ }
+ }
+ }
+
}
diff --git a/src/uk/co/majenko/audiobookrecorder/Book.java b/src/uk/co/majenko/audiobookrecorder/Book.java
index 86328fb..93ac82c 100644
--- a/src/uk/co/majenko/audiobookrecorder/Book.java
+++ b/src/uk/co/majenko/audiobookrecorder/Book.java
@@ -39,7 +39,9 @@ import org.xml.sax.SAXException;
public class Book extends BookTreeNode {
String name;
+ String shortName;
String author;
+ String shortAuthor;
String genre;
String comment;
String ACX;
@@ -53,6 +55,7 @@ public class Book extends BookTreeNode {
Random rng = new Random();
TreeMap effects;
AudioFormat cachedFormat = null;
+ ExportProfile exportProfile;
public Book(String bookname) {
super(bookname);
@@ -78,13 +81,16 @@ public class Book extends BookTreeNode {
Element root = doc.getDocumentElement();
name = getTextNode(root, "title");
+ shortName = getTextNode(root, "shorttitle");
author = getTextNode(root, "author");
+ shortAuthor = getTextNode(root, "shortauthor");
genre = getTextNode(root, "genre");
comment = getTextNode(root, "comment");
ACX = getTextNode(root, "acx");
ISBN = getTextNode(root, "isbn");
manuscript = getTextNode(root, "manuscript");
notes = getTextNode(root, "notes");
+ exportProfile = AudiobookRecorder.exportProfiles.get(getTextNode(root, "exportprofile"));
Element settings = getNode(root, "settings");
Element audioSettings = getNode(settings, "audio");
@@ -131,13 +137,16 @@ public class Book extends BookTreeNode {
public void loadBookXML(Element root, DefaultTreeModel model) {
Debug.trace();
name = getTextNode(root, "title");
+ shortName = getTextNode(root, "shorttitle");
author = getTextNode(root, "author");
+ shortAuthor = getTextNode(root, "shortauthor");
genre = getTextNode(root, "genre");
comment = getTextNode(root, "comment");
ACX = getTextNode(root, "acx");
ISBN = getTextNode(root, "isbn");
manuscript = getTextNode(root, "manuscript");
notes = getTextNode(root, "notes");
+ exportProfile = AudiobookRecorder.exportProfiles.get(getTextNode(root, "exportprofile"));
Element settings = getNode(root, "settings");
Element audioSettings = getNode(settings, "audio");
@@ -182,14 +191,18 @@ public class Book extends BookTreeNode {
}
public void setTitle(String n) { Debug.trace(); name = n; }
+ public void setShortTitle(String n) { Debug.trace(); shortName = n; }
public void setAuthor(String a) { Debug.trace(); author = a; }
+ public void setShortAuthor(String a) { Debug.trace(); shortAuthor = a; }
public void setGenre(String g) { Debug.trace(); genre = g; }
public void setComment(String c) { Debug.trace(); comment = c; }
public void setACX(String c) { Debug.trace(); ACX = c; }
public void setISBN(String c) { Debug.trace(); ISBN = c; }
public String getTitle() { Debug.trace(); return name; }
+ public String getShortTitle() { Debug.trace(); return shortName; }
public String getAuthor() { Debug.trace(); return author; }
+ public String getShortAuthor() { Debug.trace(); return shortAuthor; }
public String getGenre() { Debug.trace(); return genre; }
public String getComment() { Debug.trace(); return comment; }
public String getACX() { Debug.trace(); if (ACX == null) return ""; return ACX; }
@@ -379,6 +392,8 @@ public class Book extends BookTreeNode {
doc.appendChild(root);
root.appendChild(makeTextNode(doc, "title", name));
+ root.appendChild(makeTextNode(doc, "shortauthor", shortAuthor));
+ root.appendChild(makeTextNode(doc, "shorttitle", shortName));
root.appendChild(makeTextNode(doc, "author", author));
root.appendChild(makeTextNode(doc, "comment", comment));
root.appendChild(makeTextNode(doc, "genre", genre));
@@ -386,6 +401,9 @@ public class Book extends BookTreeNode {
root.appendChild(makeTextNode(doc, "isbn", ISBN));
root.appendChild(makeTextNode(doc, "manuscript", manuscript));
root.appendChild(makeTextNode(doc, "notes", notes));
+ if (exportProfile != null) {
+ root.appendChild(makeTextNode(doc, "exportprofile", exportProfile.getCode()));
+ }
Element settingsNode = doc.createElement("settings");
root.appendChild(settingsNode);
@@ -698,4 +716,15 @@ public class Book extends BookTreeNode {
return len;
}
+
+ public ExportProfile getExportProfile() {
+ if (exportProfile == null) {
+ return AudiobookRecorder.exportProfiles.get("librivox");
+ }
+ return exportProfile;
+ }
+
+ public void setExportProfile(ExportProfile p) {
+ exportProfile = p;
+ }
}
diff --git a/src/uk/co/majenko/audiobookrecorder/BookInfoPanel.java b/src/uk/co/majenko/audiobookrecorder/BookInfoPanel.java
index e3f4f7a..c4b59cb 100644
--- a/src/uk/co/majenko/audiobookrecorder/BookInfoPanel.java
+++ b/src/uk/co/majenko/audiobookrecorder/BookInfoPanel.java
@@ -8,17 +8,21 @@ import java.awt.GridBagConstraints;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JPanel;
+import javax.swing.JComboBox;
public class BookInfoPanel extends JPanel {
JTextField title;
+ JTextField shortTitle;
JTextField author;
+ JTextField shortAuthor;
JTextField genre;
JTextField comment;
JTextField acx;
JTextField isbn;
+ JComboBox exportProfile;
- public BookInfoPanel(String t, String a, String g, String c, String x, String i) {
+ public BookInfoPanel(String t, String st, String a, String sa, String g, String c, String x, String i, String epc) {
super();
Debug.trace();
setLayout(new GridBagLayout());
@@ -36,6 +40,15 @@ public class BookInfoPanel extends JPanel {
con.gridx = 0;
con.gridy++;
+ add(new JLabel("Short Title:"), con);
+ con.gridx = 1;
+ shortTitle = new JTextField(st);
+ shortTitle.setPreferredSize(new Dimension(200, 20));
+ add(shortTitle, con);
+
+ con.gridx = 0;
+ con.gridy++;
+
add(new JLabel("Author:"), con);
con.gridx = 1;
author = new JTextField(a);
@@ -45,6 +58,15 @@ public class BookInfoPanel extends JPanel {
con.gridx = 0;
con.gridy++;
+ add(new JLabel("Short Author:"), con);
+ con.gridx = 1;
+ shortAuthor = new JTextField(sa);
+ shortAuthor.setPreferredSize(new Dimension(200, 20));
+ add(shortAuthor, con);
+
+ con.gridx = 0;
+ con.gridy++;
+
add(new JLabel("Genre:"), con);
con.gridx = 1;
genre = new JTextField(g);
@@ -81,6 +103,20 @@ public class BookInfoPanel extends JPanel {
con.gridx = 0;
con.gridy++;
+ add(new JLabel("Export Profile:"), con);
+ con.gridx = 1;
+ exportProfile = new JComboBox();
+ for (ExportProfile profile : AudiobookRecorder.exportProfiles.values()) {
+ exportProfile.addItem(profile);
+ if (profile.getCode() == epc) {
+ exportProfile.setSelectedItem(profile);
+ }
+ }
+ add(exportProfile, con);
+
+ con.gridx = 0;
+ con.gridy++;
+
}
public String getTitle() { Debug.trace(); return title.getText(); }
@@ -97,6 +133,9 @@ public class BookInfoPanel extends JPanel {
}
return acx.getText();
}
+ public String getShortTitle() { Debug.trace(); return shortTitle.getText(); }
+ public String getShortAuthor() { Debug.trace(); return shortAuthor.getText(); }
+ public ExportProfile getExportProfile() { Debug.trace(); return (ExportProfile)exportProfile.getSelectedItem(); }
public void setTitle(String t) { Debug.trace(); title.setText(t); }
public void setAuthor(String a) { Debug.trace(); author.setText(a); }
@@ -104,5 +143,7 @@ public class BookInfoPanel extends JPanel {
public void setComment(String c) { Debug.trace(); comment.setText(c); }
public void setACX(String a) { Debug.trace(); acx.setText(a); }
public void setISBN(String i) { Debug.trace(); isbn.setText(i); }
-
+ public void setShortTitle(String t) { Debug.trace(); shortTitle.setText(t); }
+ public void setShortAuthor(String a) { Debug.trace(); shortAuthor.setText(a); }
+ public void setExportProfile(ExportProfile p) { Debug.trace(); exportProfile.setSelectedItem(p); }
}
diff --git a/src/uk/co/majenko/audiobookrecorder/Chapter.java b/src/uk/co/majenko/audiobookrecorder/Chapter.java
index cc4d941..5adec94 100644
--- a/src/uk/co/majenko/audiobookrecorder/Chapter.java
+++ b/src/uk/co/majenko/audiobookrecorder/Chapter.java
@@ -51,9 +51,6 @@ public class Chapter extends BookTreeNode {
String name;
String id;
- int preGap;
- int postGap;
-
String notes;
Book parentBook = null;
@@ -62,16 +59,12 @@ public class Chapter extends BookTreeNode {
Debug.trace();
id = i;
name = chaptername;
- preGap = Options.getInteger("catenation.pre-chapter");
- postGap = Options.getInteger("catenation.post-chapter");
}
public Chapter(Element root, DefaultTreeModel model) {
Debug.trace();
name = Book.getTextNode(root, "name");
id = root.getAttribute("id");
- preGap = Utils.s2i(Book.getTextNode(root, "pre-gap"));
- postGap = Utils.s2i(Book.getTextNode(root, "post-gap"));
notes = Book.getTextNode(root, "notes");
@@ -89,8 +82,6 @@ public class Chapter extends BookTreeNode {
Debug.trace();
name = Book.getTextNode(root, "name");
id = root.getAttribute("id");
- preGap = Utils.s2i(Book.getTextNode(root, "pre-gap"));
- postGap = Utils.s2i(Book.getTextNode(root, "post-gap"));
notes = Book.getTextNode(root, "notes");
@@ -160,26 +151,6 @@ public class Chapter extends BookTreeNode {
name = n;
}
- public void setPreGap(int g) {
- Debug.trace();
- preGap = g;
- }
-
- public int getPreGap() {
- Debug.trace();
- return preGap;
- }
-
- public void setPostGap(int g) {
- Debug.trace();
- postGap = g;
- }
-
- public int getPostGap() {
- Debug.trace();
- return postGap;
- }
-
public String createFilename(String format) {
String out = "";
@@ -198,13 +169,15 @@ public class Chapter extends BookTreeNode {
tokens.put("chapter.number", Integer.toString(getSequenceNumber()));
tokens.put("chapter.id", getId());
tokens.put("book.title", book.getTitle());
+ tokens.put("book.title.short", book.getShortTitle());
tokens.put("book.author", book.getAuthor());
+ tokens.put("book.author.short", book.getShortAuthor());
tokens.put("book.isbn", book.getISBN());
tokens.put("book.acx", book.getACX());
tokens.put("narrator.name", Options.get("narrator.name"));
tokens.put("narrator.initials", Options.get("narrator.initials"));
- tokens.put("file.bitrate", Integer.toString(Options.getInteger("audio.export.bitrate")));
- tokens.put("file.bitrate.kb", Integer.toString(Options.getInteger("audio.export.bitrate") / 1000));
+ tokens.put("file.bitrate", Integer.toString(book.getExportProfile().getExportBitrate()));
+ tokens.put("file.bitrate.kb", Integer.toString(book.getExportProfile().getExportBitrate() / 1000));
for(Map.Entry entry : tokens.entrySet()) {
format = format.replace("{" + entry.getKey() + ":lower}", entry.getValue().toLowerCase());
@@ -214,7 +187,7 @@ public class Chapter extends BookTreeNode {
}
@SuppressWarnings("unchecked")
- public void exportChapter(ProgressDialog exportDialog, String fnformat) throws
+ public void exportChapter(ProgressDialog exportDialog) throws
FileNotFoundException, IOException, InputFormatException, NotSupportedException,
EncoderException, UnsupportedTagException, InvalidDataException {
Debug.trace();
@@ -223,6 +196,10 @@ public class Chapter extends BookTreeNode {
Book book = getBook();
+ ExportProfile profile = book.getExportProfile();
+
+ String fnformat = profile.getExportFormat();
+
File export = book.getLocation("export");
if (!export.exists()) {
export.mkdirs();
@@ -243,9 +220,9 @@ public class Chapter extends BookTreeNode {
AudioAttributes audioAttributes = new AudioAttributes();
audioAttributes.setCodec("libmp3lame");
- audioAttributes.setBitRate(Options.getInteger("audio.export.bitrate"));
- audioAttributes.setSamplingRate(Options.getInteger("audio.export.samplerate"));
- audioAttributes.setChannels(Options.getInteger("audio.export.channels")); //new Integer(2));
+ audioAttributes.setBitRate(profile.getExportBitrate());
+ audioAttributes.setSamplingRate(profile.getExportSamples());
+ audioAttributes.setChannels(profile.getExportChannels());
attributes.setFormat("mp3");
attributes.setAudioAttributes(audioAttributes);
@@ -270,7 +247,7 @@ public class Chapter extends BookTreeNode {
File taggedFile = new File(export, createFilename(fnformat) + ".mp3");
FileOutputStream fos = new FileOutputStream(exportFile);
- data = getBook().getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
+ data = getBook().getRoomNoise(profile.getGapPreChapter());
fullLength += data.length;
fos.write(data);
@@ -289,7 +266,7 @@ public class Chapter extends BookTreeNode {
if (s.hasMoreElements()) {
data = getBook().getRoomNoise(snt.getPostGap());
} else {
- data = getBook().getRoomNoise(Utils.s2i(Options.get("catenation.post-chapter")));
+ data = getBook().getRoomNoise(profile.getGapPostChapter());
}
fullLength += data.length;
fos.write(data);
@@ -334,14 +311,16 @@ public class Chapter extends BookTreeNode {
public double getChapterLength() {
Debug.trace();
- double totalTime = Options.getInteger("audio.recording.pre-chapter") / 1000d;
+ Book book = getBook();
+ ExportProfile exportProfile = book.getExportProfile();
+ double totalTime = exportProfile.getGapPreChapter() / 1000d;
for (Enumeration s = children(); s.hasMoreElements();) {
Sentence sentence = (Sentence)s.nextElement();
totalTime += sentence.getLength();
if (s.hasMoreElements()) {
totalTime += (sentence.getPostGap() / 1000d);
} else {
- totalTime += Options.getInteger("audio.recording.post-chapter") / 1000d;
+ totalTime += exportProfile.getGapPostChapter() / 1000d;
}
}
return totalTime;
@@ -389,8 +368,6 @@ public class Chapter extends BookTreeNode {
Element chapterNode = doc.createElement("chapter");
chapterNode.setAttribute("id", id);
chapterNode.appendChild(Book.makeTextNode(doc, "name", name));
- chapterNode.appendChild(Book.makeTextNode(doc, "pre-gap", preGap));
- chapterNode.appendChild(Book.makeTextNode(doc, "post-gap", postGap));
chapterNode.appendChild(Book.makeTextNode(doc, "notes", notes));
Element sentencesNode = doc.createElement("sentences");
@@ -433,6 +410,9 @@ public class Chapter extends BookTreeNode {
@Override
public double getLength() {
+ Book book = getBook();
+ ExportProfile exportProfile = book.getExportProfile();
+
Debug.trace();
double len = 0;
for (Enumeration o = children(); o.hasMoreElements();) {
@@ -445,8 +425,8 @@ public class Chapter extends BookTreeNode {
}
if (len > 0) {
- len += (getPreGap() / 1000d);
- len += (getPostGap() / 1000d);
+ len += (exportProfile.getGapPreChapter() / 1000d);
+ len += (exportProfile.getGapPostChapter() / 1000d);
}
return len;
}
diff --git a/src/uk/co/majenko/audiobookrecorder/ExportProfile.java b/src/uk/co/majenko/audiobookrecorder/ExportProfile.java
new file mode 100644
index 0000000..7fa21ea
--- /dev/null
+++ b/src/uk/co/majenko/audiobookrecorder/ExportProfile.java
@@ -0,0 +1,139 @@
+package uk.co.majenko.audiobookrecorder;
+
+import java.io.File;
+import java.io.IOException;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.OutputKeys;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+
+public class ExportProfile {
+ String name;
+ String code;
+ int export_bitrate;
+ int export_channels;
+ int export_samples;
+ String export_format;
+ int gap_pre_chapter;
+ int gap_post_chapter;
+ int gap_post_sentence;
+ int gap_followon;
+ int gap_post_paragraph;
+ int gap_post_section;
+ int audio_rms;
+
+ public ExportProfile() {
+ name = "Default";
+ code = "default";
+ export_bitrate = 128000;
+ export_channels = 1;
+ export_samples = 44100;
+ export_format = "{book.title} - {chapter.number} - {chapter.title}";
+ gap_pre_chapter = 1000;
+ gap_post_chapter = 1000;
+ gap_post_sentence = 500;
+ gap_followon = 300;
+ gap_post_paragraph = 800;
+ gap_post_section = 1200;
+ audio_rms = -18;
+ }
+
+ public ExportProfile(String filename) {
+ loadProfileFromFile(new File(filename));
+ }
+
+ public ExportProfile(File f) {
+ loadProfileFromFile(f);
+ }
+
+ public void loadProfileFromFile(File inputFile) {
+ if (inputFile.exists()) {
+ try {
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ Document doc = dBuilder.parse(inputFile);
+ doc.getDocumentElement().normalize();
+ Element root = doc.getDocumentElement();
+ Element export = getNode(root, "export");
+ Element gaps = getNode(root, "gaps");
+ Element audio = getNode(root, "audio");
+
+ name = getTextNode(root, "name");
+ code = getTextNode(root, "code");
+ export_bitrate = Utils.s2i(getTextNode(export, "bitrate"));
+ export_channels = Utils.s2i(getTextNode(export, "channels"));
+ export_samples = Utils.s2i(getTextNode(export, "samples"));
+ export_format = getTextNode(export, "format");
+ gap_pre_chapter = Utils.s2i(getTextNode(gaps, "pre-chapter"));
+ gap_post_chapter = Utils.s2i(getTextNode(gaps, "post-chapter"));
+ gap_post_sentence = Utils.s2i(getTextNode(gaps, "post-sentence"));
+ gap_followon = Utils.s2i(getTextNode(gaps, "followon"));
+ gap_post_paragraph = Utils.s2i(getTextNode(gaps, "post-paragraph"));
+ gap_post_section = Utils.s2i(getTextNode(gaps, "post-section"));
+ audio_rms = Utils.s2i(getTextNode(audio, "rms"));
+
+ } catch (ParserConfigurationException ex) {
+ System.err.println("Badly formatted XML file: " + inputFile.getPath());
+ } catch (SAXException ex) {
+ System.err.println("Badly formatted XML file: " + inputFile.getPath());
+ } catch (IOException ex) {
+ System.err.println("Error reading file: " + inputFile.getPath());
+ }
+ }
+
+ }
+
+ public Element getNode(Element r, String n) {
+ Debug.trace();
+ NodeList nl = r.getElementsByTagName(n);
+ if (nl == null) return null;
+ if (nl.getLength() == 0) return null;
+ return (Element)nl.item(0);
+ }
+
+ public String getTextNode(Element r, String n) {
+ Debug.trace();
+ return getTextNode(r, n, "");
+ }
+
+ public String getTextNode(Element r, String n, String d) {
+ Debug.trace();
+ Element node = getNode(r, n);
+ if (node == null) return d;
+ return node.getTextContent();
+ }
+
+ public String getName() { return name; }
+ public String getCode() { return code; }
+ public int getExportBitrate() { return export_bitrate; }
+ public int getExportChannels() { return export_channels; }
+ public int getExportSamples() { return export_samples; }
+ public String getExportFormat() { return export_format; }
+ public int getGapPreChapter() { return gap_pre_chapter; }
+ public int getGapPostChapter() { return gap_post_chapter; }
+ public int getGapFollowon() { return gap_followon; }
+ public int getGapPostSentence() { return gap_post_sentence; }
+ public int getGapPostParagraph() { return gap_post_paragraph; }
+ public int getGapPostSection() { return gap_post_section; }
+ public int getAudioRMS() { return audio_rms; }
+
+
+ public String toString() {
+ return getName();
+ }
+
+}
diff --git a/src/uk/co/majenko/audiobookrecorder/Options.java b/src/uk/co/majenko/audiobookrecorder/Options.java
index e693900..2d2e2ab 100644
--- a/src/uk/co/majenko/audiobookrecorder/Options.java
+++ b/src/uk/co/majenko/audiobookrecorder/Options.java
@@ -377,19 +377,7 @@ public class Options extends JDialog {
addSeparator(optionsPanel);
- preChapterGap = addSpinner(optionsPanel, "Default pre-chapter gap:", 0, 5000, 100, getInteger("catenation.pre-chapter"), "ms", "How much room noise to add at the beginning of a chapter.");
- postChapterGap = addSpinner(optionsPanel, "Default post-chapter gap:", 0, 5000, 100, getInteger("catenation.post-chapter"), "ms", "How much room noise to add to the end of a chapter.");
- postSentenceGap = addSpinner(optionsPanel, "Default post-sentence gap:", 0, 5000, 100, getInteger("catenation.post-sentence"), "ms", "How much room noise to add between normal sentences.");
- shortSentenceGap = addSpinner(optionsPanel, "Short post-sentence gap:", 0, 5000, 100, getInteger("catenation.short-sentence"), "ms", "How much room noise to add between 'continuations'.");
- postParagraphGap = addSpinner(optionsPanel, "Default post-paragraph gap:", 0, 5000, 100, getInteger("catenation.post-paragraph"), "ms", "How much room noise to add between paragraphs.");
- postSectionGap = addSpinner(optionsPanel, "Default post-section gap:", 0, 5000, 100, getInteger("catenation.post-section"), "ms", "How much room noise to add between sections.");
-
- addSeparator(optionsPanel);
-
ffmpegLocation = addFilePath(optionsPanel, "FFMPEG location:", get("path.ffmpeg"), false, "Path to your ffmpeg executable.");
- bitRate = addDropdown(optionsPanel, "Export bitrate:", getBitrates(), get("audio.export.bitrate"), "The MP3 bitrate to produce");
- channels = addDropdown(optionsPanel, "Export channels:", getChannelCountList(), get("audio.export.channels"), "Mono or stereo MP3 production");
- exportRate = addDropdown(optionsPanel, "Export sample rate:", getSampleRateList(), get("audio.export.samplerate"), "Sample frequency of the produced MP3");
addSeparator(optionsPanel);
diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java
index 917a818..6d4f35f 100644
--- a/src/uk/co/majenko/audiobookrecorder/Sentence.java
+++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java
@@ -198,7 +198,6 @@ public class Sentence extends BookTreeNode implements Cacheable {
id = UUID.randomUUID().toString();
text = id;
setUserObject(text);
- postGap = Options.getInteger("catenation.post-sentence");
}
public Sentence(String i, String t) {
@@ -207,7 +206,6 @@ public class Sentence extends BookTreeNode implements Cacheable {
id = i;
text = t;
setUserObject(text);
- postGap = Options.getInteger("catenation.post-sentence");
}
public Sentence(Element root) {
@@ -990,8 +988,8 @@ public class Sentence extends BookTreeNode implements Cacheable {
Debug.trace();
if (locked) return gain;
- int targetLow = Options.getInteger("audio.recording.rms.low");
- int targetHigh = Options.getInteger("audio.recording.rms.high");
+ int targetLow = getBook().getExportProfile().getAudioRMS();
+ int targetHigh = getBook().getExportProfile().getAudioRMS();
long ts = System.currentTimeMillis();
while ((int)getRMS() < targetLow) {
@@ -1639,13 +1637,13 @@ public class Sentence extends BookTreeNode implements Cacheable {
public void setPostGapType(String t) {
Debug.trace();
if (t == null || t.equals("none")) {
- if (getPostGap() == Options.getInteger("catenation.short-sentence")) {
+ if (getPostGap() == getBook().getExportProfile().getGapFollowon()) {
t = "continuation";
- } else if (getPostGap() == Options.getInteger("catenation.post-paragraph")) {
+ } else if (getPostGap() == getBook().getExportProfile().getGapPostParagraph()) {
t = "paragraph";
- } else if (getPostGap() == Options.getInteger("catenation.post-section")) {
+ } else if (getPostGap() == getBook().getExportProfile().getGapPostSection()) {
t = "section";
- } else if (getPostGap() == Options.getInteger("catenation.post-sentence")) {
+ } else if (getPostGap() == getBook().getExportProfile().getGapPostSentence()) {
t = "sentence";
} else {
t = "sentence";
@@ -1661,13 +1659,13 @@ public class Sentence extends BookTreeNode implements Cacheable {
postGapType = "sentence";
}
if (postGapType.equals("continuation")) {
- setPostGap(Options.getInteger("catenation.short-sentence"));
+ setPostGap(getBook().getExportProfile().getGapFollowon());
} else if (postGapType.equals("paragraph")) {
- setPostGap(Options.getInteger("catenation.post-paragraph"));
+ setPostGap(getBook().getExportProfile().getGapPostParagraph());
} else if (postGapType.equals("section")) {
- setPostGap(Options.getInteger("catenation.post-section"));
+ setPostGap(getBook().getExportProfile().getGapPostSection());
} else {
- setPostGap(Options.getInteger("catenation.post-sentence"));
+ setPostGap(getBook().getExportProfile().getGapPostSentence());
}
}