Improved export facility and added export single chapter
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -2,6 +2,6 @@
|
|||||||
._*
|
._*
|
||||||
bin
|
bin
|
||||||
AudiobookRecorder.jar
|
AudiobookRecorder.jar
|
||||||
AudiobookRecorder.dmg
|
AudiobookRecorder-linux
|
||||||
AudiobookRecorder.exe
|
AudiobookRecorder-osx.dmg
|
||||||
AudiobookRecorder
|
AudiobookRecorder-win.exe
|
||||||
|
|||||||
@@ -798,6 +798,21 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
JMenu mergeWith = new JMenu("Merge chapter with");
|
JMenu mergeWith = new JMenu("Merge chapter with");
|
||||||
JMenuObject lockAll = new JMenuObject("Lock all sentences", c);
|
JMenuObject lockAll = new JMenuObject("Lock all sentences", c);
|
||||||
JMenuObject unlockAll = new JMenuObject("Unlock all sentences", c);
|
JMenuObject unlockAll = new JMenuObject("Unlock all sentences", c);
|
||||||
|
JMenuObject exportChapter = new JMenuObject("Export chapter", c);
|
||||||
|
|
||||||
|
exportChapter.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
JMenuObject o = (JMenuObject)e.getSource();
|
||||||
|
Chapter chap = (Chapter)o.getObject();
|
||||||
|
|
||||||
|
ExportDialog ed = new ExportDialog("Exporting " + chap.getName());
|
||||||
|
|
||||||
|
ExportThread t = new ExportThread(chap, ed);
|
||||||
|
Thread nt = new Thread(t);
|
||||||
|
nt.start();
|
||||||
|
ed.setVisible(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (Enumeration<Chapter> bc = book.children(); bc.hasMoreElements();) {
|
for (Enumeration<Chapter> bc = book.children(); bc.hasMoreElements();) {
|
||||||
Chapter chp = bc.nextElement();
|
Chapter chp = bc.nextElement();
|
||||||
@@ -824,7 +839,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int idNumber = s2i(c.getId());
|
int idNumber = Utils.s2i(c.getId());
|
||||||
|
|
||||||
moveUp.setEnabled(idNumber > 0);
|
moveUp.setEnabled(idNumber > 0);
|
||||||
moveDown.setEnabled(idNumber > 0);
|
moveDown.setEnabled(idNumber > 0);
|
||||||
@@ -836,10 +851,10 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
int pos = bookTreeModel.getIndexOfChild(book, chap);
|
int pos = bookTreeModel.getIndexOfChild(book, chap);
|
||||||
if (pos > 0) pos--;
|
if (pos > 0) pos--;
|
||||||
|
|
||||||
int id = s2i(chap.getId());
|
int id = Utils.s2i(chap.getId());
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
Chapter prevChap = (Chapter)bookTreeModel.getChild(book, pos);
|
Chapter prevChap = (Chapter)bookTreeModel.getChild(book, pos);
|
||||||
id = s2i(prevChap.getId());
|
id = Utils.s2i(prevChap.getId());
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
bookTreeModel.removeNodeFromParent(chap);
|
bookTreeModel.removeNodeFromParent(chap);
|
||||||
bookTreeModel.insertNodeInto(chap, book, pos);
|
bookTreeModel.insertNodeInto(chap, book, pos);
|
||||||
@@ -853,11 +868,11 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
Chapter chap = (Chapter)o.getObject();
|
Chapter chap = (Chapter)o.getObject();
|
||||||
int pos = bookTreeModel.getIndexOfChild(book, chap);
|
int pos = bookTreeModel.getIndexOfChild(book, chap);
|
||||||
pos++;
|
pos++;
|
||||||
int id = s2i(chap.getId());
|
int id = Utils.s2i(chap.getId());
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
Chapter nextChap = (Chapter)bookTreeModel.getChild(book, pos);
|
Chapter nextChap = (Chapter)bookTreeModel.getChild(book, pos);
|
||||||
if (nextChap != null) {
|
if (nextChap != null) {
|
||||||
id = s2i(nextChap.getId());
|
id = Utils.s2i(nextChap.getId());
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
bookTreeModel.removeNodeFromParent(chap);
|
bookTreeModel.removeNodeFromParent(chap);
|
||||||
bookTreeModel.insertNodeInto(chap, book, pos);
|
bookTreeModel.insertNodeInto(chap, book, pos);
|
||||||
@@ -913,9 +928,16 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
menu.add(peak);
|
menu.add(peak);
|
||||||
|
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
|
|
||||||
menu.add(lockAll);
|
menu.add(lockAll);
|
||||||
menu.add(unlockAll);
|
menu.add(unlockAll);
|
||||||
|
|
||||||
|
menu.addSeparator();
|
||||||
|
|
||||||
|
menu.add(exportChapter);
|
||||||
|
|
||||||
menu.show(bookTree, e.getX(), e.getY());
|
menu.show(bookTree, e.getX(), e.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1279,38 +1301,38 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
|
|
||||||
Chapter c = new Chapter("audition", prefs.getProperty("chapter.audition.name"));
|
Chapter c = new Chapter("audition", prefs.getProperty("chapter.audition.name"));
|
||||||
c.setPostGap(s2i(prefs.getProperty("chapter.audition.post-gap")));
|
c.setPostGap(Utils.s2i(prefs.getProperty("chapter.audition.post-gap")));
|
||||||
c.setPreGap(s2i(prefs.getProperty("chapter.audition.pre-gap")));
|
c.setPreGap(Utils.s2i(prefs.getProperty("chapter.audition.pre-gap")));
|
||||||
bookTreeModel.insertNodeInto(c, book, 0);
|
bookTreeModel.insertNodeInto(c, book, 0);
|
||||||
|
|
||||||
for (int i = 0; i < 100000000; i++) {
|
for (int i = 0; i < 100000000; i++) {
|
||||||
String id = prefs.getProperty(String.format("chapter.audition.sentence.%08d.id", i));
|
String id = prefs.getProperty(String.format("chapter.audition.sentence.%08d.id", i));
|
||||||
String text = prefs.getProperty(String.format("chapter.audition.sentence.%08d.text", i));
|
String text = prefs.getProperty(String.format("chapter.audition.sentence.%08d.text", i));
|
||||||
int gap = s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.post-gap", i)));
|
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.post-gap", i)));
|
||||||
if (id == null) break;
|
if (id == null) break;
|
||||||
Sentence s = new Sentence(id, text);
|
Sentence s = new Sentence(id, text);
|
||||||
s.setPostGap(gap);
|
s.setPostGap(gap);
|
||||||
s.setStartOffset(s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.start-offset", i))));
|
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.start-offset", i))));
|
||||||
s.setEndOffset(s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.end-offset", i))));
|
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.end-offset", i))));
|
||||||
s.setLocked(s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.locked", i))));
|
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.locked", i))));
|
||||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
c = new Chapter("open", prefs.getProperty("chapter.open.name"));
|
c = new Chapter("open", prefs.getProperty("chapter.open.name"));
|
||||||
c.setPostGap(s2i(prefs.getProperty("chapter.open.post-gap")));
|
c.setPostGap(Utils.s2i(prefs.getProperty("chapter.open.post-gap")));
|
||||||
c.setPreGap(s2i(prefs.getProperty("chapter.open.pre-gap")));
|
c.setPreGap(Utils.s2i(prefs.getProperty("chapter.open.pre-gap")));
|
||||||
bookTreeModel.insertNodeInto(c, book, 0);
|
bookTreeModel.insertNodeInto(c, book, 0);
|
||||||
|
|
||||||
for (int i = 0; i < 100000000; i++) {
|
for (int i = 0; i < 100000000; i++) {
|
||||||
String id = prefs.getProperty(String.format("chapter.open.sentence.%08d.id", i));
|
String id = prefs.getProperty(String.format("chapter.open.sentence.%08d.id", i));
|
||||||
String text = prefs.getProperty(String.format("chapter.open.sentence.%08d.text", i));
|
String text = prefs.getProperty(String.format("chapter.open.sentence.%08d.text", i));
|
||||||
int gap = s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.post-gap", i)));
|
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.post-gap", i)));
|
||||||
if (id == null) break;
|
if (id == null) break;
|
||||||
Sentence s = new Sentence(id, text);
|
Sentence s = new Sentence(id, text);
|
||||||
s.setPostGap(gap);
|
s.setPostGap(gap);
|
||||||
s.setStartOffset(s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.start-offset", i))));
|
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.start-offset", i))));
|
||||||
s.setEndOffset(s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.end-offset", i))));
|
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.end-offset", i))));
|
||||||
s.setLocked(s2b(prefs.getProperty(String.format("chapter.open.sentence.%08d.locked", i))));
|
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.open.sentence.%08d.locked", i))));
|
||||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1321,39 +1343,39 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
if (cname == null) break;
|
if (cname == null) break;
|
||||||
|
|
||||||
c = new Chapter(String.format("%04d", cno), cname);
|
c = new Chapter(String.format("%04d", cno), cname);
|
||||||
c.setPostGap(s2i(prefs.getProperty(String.format("chapter.%04d.post-gap", cno))));
|
c.setPostGap(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.post-gap", cno))));
|
||||||
c.setPreGap(s2i(prefs.getProperty(String.format("chapter.%04d.pre-gap", cno))));
|
c.setPreGap(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.pre-gap", cno))));
|
||||||
bookTreeModel.insertNodeInto(c, book, book.getChildCount());
|
bookTreeModel.insertNodeInto(c, book, book.getChildCount());
|
||||||
|
|
||||||
for (int i = 0; i < 100000000; i++) {
|
for (int i = 0; i < 100000000; i++) {
|
||||||
String id = prefs.getProperty(String.format("chapter.%04d.sentence.%08d.id", cno, i));
|
String id = prefs.getProperty(String.format("chapter.%04d.sentence.%08d.id", cno, i));
|
||||||
String text = prefs.getProperty(String.format("chapter.%04d.sentence.%08d.text", cno, i));
|
String text = prefs.getProperty(String.format("chapter.%04d.sentence.%08d.text", cno, i));
|
||||||
int gap = s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.post-gap", cno, i)));
|
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.post-gap", cno, i)));
|
||||||
if (id == null) break;
|
if (id == null) break;
|
||||||
Sentence s = new Sentence(id, text);
|
Sentence s = new Sentence(id, text);
|
||||||
s.setPostGap(gap);
|
s.setPostGap(gap);
|
||||||
s.setStartOffset(s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.start-offset", cno, i))));
|
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.start-offset", cno, i))));
|
||||||
s.setEndOffset(s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.end-offset", cno, i))));
|
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.end-offset", cno, i))));
|
||||||
s.setLocked(s2b(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.locked", cno, i))));
|
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.locked", cno, i))));
|
||||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = new Chapter("close", prefs.getProperty("chapter.close.name"));
|
c = new Chapter("close", prefs.getProperty("chapter.close.name"));
|
||||||
c.setPostGap(s2i(prefs.getProperty("chapter.close.post-gap")));
|
c.setPostGap(Utils.s2i(prefs.getProperty("chapter.close.post-gap")));
|
||||||
c.setPreGap(s2i(prefs.getProperty("chapter.close.pre-gap")));
|
c.setPreGap(Utils.s2i(prefs.getProperty("chapter.close.pre-gap")));
|
||||||
bookTreeModel.insertNodeInto(c, book, book.getChildCount());
|
bookTreeModel.insertNodeInto(c, book, book.getChildCount());
|
||||||
|
|
||||||
for (int i = 0; i < 100000000; i++) {
|
for (int i = 0; i < 100000000; i++) {
|
||||||
String id = prefs.getProperty(String.format("chapter.close.sentence.%08d.id", i));
|
String id = prefs.getProperty(String.format("chapter.close.sentence.%08d.id", i));
|
||||||
String text = prefs.getProperty(String.format("chapter.close.sentence.%08d.text", i));
|
String text = prefs.getProperty(String.format("chapter.close.sentence.%08d.text", i));
|
||||||
int gap = s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.post-gap", i)));
|
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.post-gap", i)));
|
||||||
if (id == null) break;
|
if (id == null) break;
|
||||||
Sentence s = new Sentence(id, text);
|
Sentence s = new Sentence(id, text);
|
||||||
s.setPostGap(gap);
|
s.setPostGap(gap);
|
||||||
s.setStartOffset(s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.start-offset", i))));
|
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.start-offset", i))));
|
||||||
s.setEndOffset(s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.end-offset", i))));
|
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.end-offset", i))));
|
||||||
s.setLocked(s2b(prefs.getProperty(String.format("chapter.close.sentence.%08d.locked", i))));
|
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.close.sentence.%08d.locked", i))));
|
||||||
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,23 +1417,6 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean s2b(String s) {
|
|
||||||
if (s == null) return false;
|
|
||||||
if (s.equals("true")) return true;
|
|
||||||
if (s.equals("t")) return true;
|
|
||||||
if (s.equals("yes")) return true;
|
|
||||||
if (s.equals("y")) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s2i(String s) {
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(s);
|
|
||||||
} catch (Exception e) {
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getBookFolder() {
|
public File getBookFolder() {
|
||||||
File bf = new File(Options.get("path.storage"), book.getName());
|
File bf = new File(Options.get("path.storage"), book.getName());
|
||||||
if (!bf.exists()) {
|
if (!bf.exists()) {
|
||||||
@@ -1480,141 +1485,19 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
class ExportThread implements Runnable {
|
class ExportThread implements Runnable {
|
||||||
ExportDialog exportDialog;
|
ExportDialog exportDialog;
|
||||||
|
Chapter chapter;
|
||||||
|
|
||||||
public ExportThread(ExportDialog e) {
|
public ExportThread(Chapter c, ExportDialog e) {
|
||||||
super();
|
super();
|
||||||
exportDialog = e;
|
exportDialog = e;
|
||||||
|
chapter = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
File bookRoot = new File(Options.get("path.storage"), book.getName());
|
chapter.exportChapter(exportDialog);
|
||||||
if (!bookRoot.exists()) {
|
|
||||||
bookRoot.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
File export = new File(bookRoot, "export");
|
|
||||||
if (!export.exists()) {
|
|
||||||
export.mkdirs();
|
|
||||||
}
|
|
||||||
Encoder encoder;
|
|
||||||
|
|
||||||
String ffloc = Options.get("path.ffmpeg");
|
|
||||||
if (ffloc != null && !ffloc.equals("")) {
|
|
||||||
encoder = new Encoder(new FFMPEGLocator() {
|
|
||||||
public String getFFMPEGExecutablePath() {
|
|
||||||
return Options.get("path.ffmpeg");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
encoder = new Encoder();
|
|
||||||
}
|
|
||||||
EncodingAttributes attributes = new EncodingAttributes();
|
|
||||||
|
|
||||||
AudioAttributes audioAttributes = new AudioAttributes();
|
|
||||||
audioAttributes.setCodec("libmp3lame");
|
|
||||||
audioAttributes.setBitRate(Options.getInteger("audio.export.bitrate"));
|
|
||||||
audioAttributes.setSamplingRate(Options.getInteger("audio.export.samplerate"));
|
|
||||||
audioAttributes.setChannels(new Integer(2));
|
|
||||||
attributes.setFormat("mp3");
|
|
||||||
attributes.setAudioAttributes(audioAttributes);
|
|
||||||
|
|
||||||
|
|
||||||
AudioFormat format = roomNoise.getAudioFormat();
|
|
||||||
byte[] data;
|
|
||||||
|
|
||||||
for (Enumeration<Chapter> o = book.children(); o.hasMoreElements();) {
|
|
||||||
|
|
||||||
int fullLength = 0;
|
|
||||||
|
|
||||||
|
|
||||||
Chapter c = o.nextElement();
|
|
||||||
|
|
||||||
if (c.getChildCount() == 0) continue;
|
|
||||||
int kids = c.getChildCount();
|
|
||||||
if (kids == 0) continue;
|
|
||||||
String name = c.getName();
|
|
||||||
exportDialog.setMessage("Exporting " + name);
|
|
||||||
exportDialog.setProgress(0);
|
|
||||||
|
|
||||||
File exportFile = new File(export, name + ".wax");
|
|
||||||
File wavFile = new File(export, name + ".wav");
|
|
||||||
|
|
||||||
FileOutputStream fos = new FileOutputStream(exportFile);
|
|
||||||
data = getRoomNoise(s2i(Options.get("catenation.pre-chapter")));
|
|
||||||
fullLength += data.length;
|
|
||||||
fos.write(data);
|
|
||||||
|
|
||||||
int kidno = 0;
|
|
||||||
|
|
||||||
|
|
||||||
for (Enumeration<Sentence> s = c.children(); s.hasMoreElements();) {
|
|
||||||
kidno++;
|
|
||||||
exportDialog.setProgress(kidno * 1000 / kids);
|
|
||||||
Sentence snt = s.nextElement();
|
|
||||||
data = snt.getRawAudioData();
|
|
||||||
|
|
||||||
fullLength += data.length;
|
|
||||||
fos.write(data);
|
|
||||||
|
|
||||||
if (s.hasMoreElements()) {
|
|
||||||
data = getRoomNoise(snt.getPostGap());
|
|
||||||
} else {
|
|
||||||
data = getRoomNoise(s2i(Options.get("catenation.post-chapter")));
|
|
||||||
}
|
|
||||||
fullLength += data.length;
|
|
||||||
fos.write(data);
|
|
||||||
}
|
|
||||||
fos.close();
|
|
||||||
FileInputStream fis = new FileInputStream(exportFile);
|
|
||||||
AudioInputStream ais = new AudioInputStream(fis, format, fullLength);
|
|
||||||
fos = new FileOutputStream(wavFile);
|
|
||||||
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, fos);
|
|
||||||
fos.flush();
|
|
||||||
fos.close();
|
|
||||||
fis.close();
|
|
||||||
exportFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (Enumeration<Chapter> o = book.children(); o.hasMoreElements();) {
|
|
||||||
|
|
||||||
Chapter c = o.nextElement();
|
|
||||||
if (c.getChildCount() == 0) continue;
|
|
||||||
String name = c.getName();
|
|
||||||
|
|
||||||
exportDialog.setMessage("Converting " + name);
|
|
||||||
|
|
||||||
File wavFile = new File(export, name + ".wav");
|
|
||||||
File mp3File = new File(export, name + "-untagged.mp3");
|
|
||||||
File taggedFile = new File(export, name + ".mp3");
|
|
||||||
|
|
||||||
encoder.encode(wavFile, mp3File, attributes, exportDialog);
|
|
||||||
|
|
||||||
Mp3File id3 = new Mp3File(mp3File);
|
|
||||||
|
|
||||||
ID3v2 tags = new ID3v24Tag();
|
|
||||||
id3.setId3v2Tag(tags);
|
|
||||||
|
|
||||||
tags.setTrack(Integer.toString(s2i(c.getId()) - 0));
|
|
||||||
tags.setTitle(c.getName());
|
|
||||||
tags.setAlbum(book.getName());
|
|
||||||
tags.setArtist(book.getAuthor());
|
|
||||||
|
|
||||||
// ID3v2TextFrameData g = new ID3v2TextFrameData(false, new EncodedText(book.getGenre()));
|
|
||||||
// tags.addFrame(tags.createFrame("TCON", g.toBytes(), true));
|
|
||||||
|
|
||||||
tags.setComment(book.getComment());
|
|
||||||
|
|
||||||
id3.save(taggedFile.getAbsolutePath());
|
|
||||||
mp3File.delete();
|
|
||||||
wavFile.delete();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -1626,14 +1509,20 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void exportAudio() {
|
public void exportAudio() {
|
||||||
|
|
||||||
ExportDialog ed = new ExportDialog("Exporting book...");
|
|
||||||
|
|
||||||
ExportThread t = new ExportThread(ed);
|
for (Enumeration<Chapter> o = book.children(); o.hasMoreElements();) {
|
||||||
|
Chapter c = o.nextElement();
|
||||||
|
ExportDialog ed = new ExportDialog("Exporting " + c.getName());
|
||||||
|
|
||||||
|
ExportThread t = new ExportThread(c, ed);
|
||||||
Thread nt = new Thread(t);
|
Thread nt = new Thread(t);
|
||||||
nt.start();
|
nt.start();
|
||||||
ed.setVisible(true);
|
ed.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JOptionPane.showMessageDialog(this, "Book export finished", "Export finished", JOptionPane.PLAIN_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void playFromSelectedSentence() {
|
public void playFromSelectedSentence() {
|
||||||
if (selectedSentence == null) return;
|
if (selectedSentence == null) return;
|
||||||
@@ -1668,7 +1557,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
first = true;
|
first = true;
|
||||||
}
|
}
|
||||||
if (first) {
|
if (first) {
|
||||||
data = getRoomNoise(s2i(Options.get("catenation.pre-chapter")));
|
data = getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
|
||||||
play.write(data, 0, data.length);
|
play.write(data, 0, data.length);
|
||||||
}
|
}
|
||||||
data = s.getRawAudioData();
|
data = s.getRawAudioData();
|
||||||
@@ -1683,7 +1572,7 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
data = getRoomNoise(s2i(Options.get("catenation.post-chapter")));
|
data = getRoomNoise(Utils.s2i(Options.get("catenation.post-chapter")));
|
||||||
play.write(data, 0, data.length);
|
play.write(data, 0, data.length);
|
||||||
playing = null;
|
playing = null;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import java.util.*;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import javax.swing.tree.*;
|
import javax.swing.tree.*;
|
||||||
|
import it.sauronsoftware.jave.*;
|
||||||
|
import com.mpatric.mp3agic.*;
|
||||||
|
import javax.sound.sampled.*;
|
||||||
|
|
||||||
|
|
||||||
public class Chapter extends DefaultMutableTreeNode {
|
public class Chapter extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
@@ -71,4 +75,125 @@ public class Chapter extends DefaultMutableTreeNode {
|
|||||||
public int getPostGap() {
|
public int getPostGap() {
|
||||||
return postGap;
|
return postGap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void exportChapter(ExportDialog exportDialog) throws
|
||||||
|
FileNotFoundException, IOException, InputFormatException, NotSupportedException,
|
||||||
|
EncoderException, UnsupportedTagException, InvalidDataException {
|
||||||
|
|
||||||
|
if (getChildCount() == 0) return;
|
||||||
|
|
||||||
|
Book book = AudiobookRecorder.window.book;
|
||||||
|
|
||||||
|
File bookRoot = new File(Options.get("path.storage"), book.getName());
|
||||||
|
if (!bookRoot.exists()) {
|
||||||
|
bookRoot.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
File export = new File(bookRoot, "export");
|
||||||
|
if (!export.exists()) {
|
||||||
|
export.mkdirs();
|
||||||
|
}
|
||||||
|
Encoder encoder;
|
||||||
|
|
||||||
|
String ffloc = Options.get("path.ffmpeg");
|
||||||
|
if (ffloc != null && !ffloc.equals("")) {
|
||||||
|
encoder = new Encoder(new FFMPEGLocator() {
|
||||||
|
public String getFFMPEGExecutablePath() {
|
||||||
|
return Options.get("path.ffmpeg");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
encoder = new Encoder();
|
||||||
|
}
|
||||||
|
EncodingAttributes attributes = new EncodingAttributes();
|
||||||
|
|
||||||
|
AudioAttributes audioAttributes = new AudioAttributes();
|
||||||
|
audioAttributes.setCodec("libmp3lame");
|
||||||
|
audioAttributes.setBitRate(Options.getInteger("audio.export.bitrate"));
|
||||||
|
audioAttributes.setSamplingRate(Options.getInteger("audio.export.samplerate"));
|
||||||
|
audioAttributes.setChannels(new Integer(2));
|
||||||
|
attributes.setFormat("mp3");
|
||||||
|
attributes.setAudioAttributes(audioAttributes);
|
||||||
|
|
||||||
|
|
||||||
|
AudioFormat format = AudiobookRecorder.window.roomNoise.getAudioFormat();
|
||||||
|
byte[] data;
|
||||||
|
|
||||||
|
int fullLength = 0;
|
||||||
|
|
||||||
|
int kids = getChildCount();
|
||||||
|
|
||||||
|
String name = getName();
|
||||||
|
if (exportDialog != null) exportDialog.setMessage("Exporting " + name);
|
||||||
|
if (exportDialog != null) exportDialog.setProgress(0);
|
||||||
|
|
||||||
|
File exportFile = new File(export, name + ".wax");
|
||||||
|
File wavFile = new File(export, name + ".wav");
|
||||||
|
File mp3File = new File(export, name + "-untagged.mp3");
|
||||||
|
File taggedFile = new File(export, name + ".mp3");
|
||||||
|
|
||||||
|
FileOutputStream fos = new FileOutputStream(exportFile);
|
||||||
|
data = AudiobookRecorder.window.getRoomNoise(Utils.s2i(Options.get("catenation.pre-chapter")));
|
||||||
|
fullLength += data.length;
|
||||||
|
fos.write(data);
|
||||||
|
|
||||||
|
int kidno = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for (Enumeration<Sentence> s = children(); s.hasMoreElements();) {
|
||||||
|
kidno++;
|
||||||
|
if (exportDialog != null) exportDialog.setProgress(kidno * 1000 / kids);
|
||||||
|
Sentence snt = s.nextElement();
|
||||||
|
data = snt.getRawAudioData();
|
||||||
|
|
||||||
|
fullLength += data.length;
|
||||||
|
fos.write(data);
|
||||||
|
|
||||||
|
if (s.hasMoreElements()) {
|
||||||
|
data = AudiobookRecorder.window.getRoomNoise(snt.getPostGap());
|
||||||
|
} else {
|
||||||
|
data = AudiobookRecorder.window.getRoomNoise(Utils.s2i(Options.get("catenation.post-chapter")));
|
||||||
|
}
|
||||||
|
fullLength += data.length;
|
||||||
|
fos.write(data);
|
||||||
|
}
|
||||||
|
fos.close();
|
||||||
|
FileInputStream fis = new FileInputStream(exportFile);
|
||||||
|
AudioInputStream ais = new AudioInputStream(fis, format, fullLength);
|
||||||
|
fos = new FileOutputStream(wavFile);
|
||||||
|
AudioSystem.write(ais, AudioFileFormat.Type.WAVE, fos);
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
fis.close();
|
||||||
|
exportFile.delete();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (exportDialog != null) exportDialog.setMessage("Converting " + name);
|
||||||
|
|
||||||
|
|
||||||
|
if (exportDialog != null) {
|
||||||
|
encoder.encode(wavFile, mp3File, attributes, exportDialog);
|
||||||
|
} else {
|
||||||
|
encoder.encode(wavFile, mp3File, attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mp3File id3 = new Mp3File(mp3File);
|
||||||
|
|
||||||
|
ID3v2 tags = new ID3v24Tag();
|
||||||
|
id3.setId3v2Tag(tags);
|
||||||
|
|
||||||
|
tags.setTrack(Integer.toString(Utils.s2i(getId()) - 0));
|
||||||
|
tags.setTitle(name);
|
||||||
|
tags.setAlbum(book.getName());
|
||||||
|
tags.setArtist(book.getAuthor());
|
||||||
|
|
||||||
|
tags.setComment(book.getComment());
|
||||||
|
|
||||||
|
id3.save(taggedFile.getAbsolutePath());
|
||||||
|
mp3File.delete();
|
||||||
|
wavFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,11 +68,15 @@ public class ExportDialog extends JDialog implements EncoderProgressListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void progress(int p) { setProgress(p); }
|
public void progress(int p) {
|
||||||
|
progress.setValue(500 + (p / 2));
|
||||||
|
progress.setString((50 + p / 20) + "%");
|
||||||
|
spin();
|
||||||
|
}
|
||||||
|
|
||||||
public void setProgress(int p) {
|
public void setProgress(int p) {
|
||||||
progress.setValue(p);
|
progress.setValue(p / 2);
|
||||||
progress.setString((p / 10) + "%");
|
progress.setString((p / 20) + "%");
|
||||||
spin();
|
spin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,22 @@ public class Utils {
|
|||||||
|
|
||||||
return resizedImg;
|
return resizedImg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean s2b(String s) {
|
||||||
|
if (s == null) return false;
|
||||||
|
if (s.equals("true")) return true;
|
||||||
|
if (s.equals("t")) return true;
|
||||||
|
if (s.equals("yes")) return true;
|
||||||
|
if (s.equals("y")) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int s2i(String s) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(s);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user