Added progress dialog while exporting #14
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 896 B |
Binary file not shown.
|
After Width: | Height: | Size: 885 B |
Binary file not shown.
|
After Width: | Height: | Size: 834 B |
Binary file not shown.
|
After Width: | Height: | Size: 839 B |
@@ -41,6 +41,9 @@ public class Encoder {
|
|||||||
private static final Pattern FORMAT_PATTERN = Pattern
|
private static final Pattern FORMAT_PATTERN = Pattern
|
||||||
.compile("^\\s*([D ])([E ])\\s+([\\w,]+)\\s+.+$");
|
.compile("^\\s*([D ])([E ])\\s+([\\w,]+)\\s+.+$");
|
||||||
|
|
||||||
|
private static final Pattern TIME_PATTERN = Pattern
|
||||||
|
.compile("^(\\d+):(\\d+):(\\d+)\\.(\\d+)$");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This regexp is used to parse the ffmpeg output about the included
|
* This regexp is used to parse the ffmpeg output about the included
|
||||||
* encoders/decoders.
|
* encoders/decoders.
|
||||||
@@ -895,26 +898,52 @@ public class Encoder {
|
|||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
String time = (String) table.get("time");
|
String time = (String) table.get("time");
|
||||||
if (time != null) {
|
if (time != null) {
|
||||||
int dot = time.indexOf('.');
|
|
||||||
if (dot > 0 && dot == time.length() - 2
|
Matcher tm = TIME_PATTERN.matcher(time);
|
||||||
&& duration > 0) {
|
if (tm.matches()) {
|
||||||
String p1 = time.substring(0, dot);
|
try {
|
||||||
String p2 = time.substring(dot + 1);
|
long hours = Long.parseLong(tm.group(1));
|
||||||
try {
|
long minutes = Long.parseLong(tm.group(2));
|
||||||
long i1 = Long.parseLong(p1);
|
long seconds = Long.parseLong(tm.group(3));
|
||||||
long i2 = Long.parseLong(p2);
|
long millis = Long.parseLong(tm.group(4));
|
||||||
progress = (i1 * 1000L)
|
progress = (hours * 3600L * 1000L) +
|
||||||
+ (i2 * 100L);
|
(minutes * 60L * 1000L) +
|
||||||
int perm = (int) Math
|
(seconds * 1000L) +
|
||||||
.round((double) (progress * 1000L)
|
(millis * 100L);
|
||||||
/ (double) duration);
|
|
||||||
if (perm > 1000) {
|
int perm = (int) Math
|
||||||
perm = 1000;
|
.round((double) (progress * 1000L)
|
||||||
}
|
/ (double) duration);
|
||||||
listener.progress(perm);
|
if (perm > 1000) {
|
||||||
} catch (NumberFormatException e) {
|
perm = 1000;
|
||||||
;
|
}
|
||||||
}
|
listener.progress(perm);
|
||||||
|
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int dot = time.indexOf('.');
|
||||||
|
if (dot > 0 && dot == time.length() - 2
|
||||||
|
&& duration > 0) {
|
||||||
|
String p1 = time.substring(0, dot);
|
||||||
|
String p2 = time.substring(dot + 1);
|
||||||
|
try {
|
||||||
|
long i1 = Long.parseLong(p1);
|
||||||
|
long i2 = Long.parseLong(p2);
|
||||||
|
progress = (i1 * 1000L)
|
||||||
|
+ (i2 * 100L);
|
||||||
|
int perm = (int) Math
|
||||||
|
.round((double) (progress * 1000L)
|
||||||
|
/ (double) duration);
|
||||||
|
if (perm > 1000) {
|
||||||
|
perm = 1000;
|
||||||
|
}
|
||||||
|
listener.progress(perm);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1145,13 +1145,20 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FileOutputStream fos = new FileOutputStream(config);
|
fos = new FileOutputStream(config);
|
||||||
prefs.storeToXML(fos, "Audiobook Recorder Description");
|
prefs.storeToXML(fos, "Audiobook Recorder Description");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
if (fos != null) {
|
||||||
|
try {
|
||||||
|
fos.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadBookStructure(File f) {
|
public void loadBookStructure(File f) {
|
||||||
@@ -1471,133 +1478,160 @@ public class AudiobookRecorder extends JFrame {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExportThread implements Runnable {
|
||||||
|
ExportDialog exportDialog;
|
||||||
|
|
||||||
|
public ExportThread(ExportDialog e) {
|
||||||
|
super();
|
||||||
|
exportDialog = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
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 = 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) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
exportDialog.closeDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void exportAudio() {
|
public void exportAudio() {
|
||||||
|
|
||||||
try {
|
ExportDialog ed = new ExportDialog("Exporting book...");
|
||||||
File bookRoot = new File(Options.get("path.storage"), book.getName());
|
|
||||||
if (!bookRoot.exists()) {
|
|
||||||
bookRoot.mkdirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
File export = new File(bookRoot, "export");
|
ExportThread t = new ExportThread(ed);
|
||||||
if (!export.exists()) {
|
Thread nt = new Thread(t);
|
||||||
export.mkdirs();
|
nt.start();
|
||||||
}
|
ed.setVisible(true);
|
||||||
|
|
||||||
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;
|
|
||||||
String name = c.getName();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
for (Enumeration<Sentence> s = c.children(); s.hasMoreElements();) {
|
|
||||||
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();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JOptionPane.showMessageDialog(this, "Book exported.", "Done", JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package uk.co.majenko.audiobookrecorder;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import javax.swing.border.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.*;
|
||||||
|
import it.sauronsoftware.jave.*;
|
||||||
|
|
||||||
|
public class ExportDialog extends JDialog implements EncoderProgressListener {
|
||||||
|
JLabel message;
|
||||||
|
JLabel icon;
|
||||||
|
|
||||||
|
JProgressBar progress;
|
||||||
|
|
||||||
|
int spin = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public ExportDialog(String m) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
|
||||||
|
|
||||||
|
message = new JLabel(m);
|
||||||
|
icon = new JLabel(Icons.spinner0);
|
||||||
|
progress = new JProgressBar(0, 1000);
|
||||||
|
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
add(message, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
icon.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
|
||||||
|
add(icon, BorderLayout.WEST);
|
||||||
|
|
||||||
|
|
||||||
|
add(progress, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
setLocationRelativeTo(AudiobookRecorder.window);
|
||||||
|
|
||||||
|
setPreferredSize(new Dimension(300, 100));
|
||||||
|
|
||||||
|
pack();
|
||||||
|
|
||||||
|
setSize(new Dimension(300, 100));
|
||||||
|
|
||||||
|
// setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String m) {
|
||||||
|
message.setText(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeDialog() {
|
||||||
|
dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spin() {
|
||||||
|
spin++;
|
||||||
|
if (spin == 4) spin = 0;
|
||||||
|
|
||||||
|
switch (spin) {
|
||||||
|
case 0: icon.setIcon(Icons.spinner0); break;
|
||||||
|
case 1: icon.setIcon(Icons.spinner1); break;
|
||||||
|
case 2: icon.setIcon(Icons.spinner2); break;
|
||||||
|
case 3: icon.setIcon(Icons.spinner3); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void progress(int p) { setProgress(p); }
|
||||||
|
|
||||||
|
public void setProgress(int p) {
|
||||||
|
progress.setValue(p);
|
||||||
|
progress.setString((p / 10) + "%");
|
||||||
|
spin();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void message(String m) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sourceInfo(MultimediaInfo i) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,5 +22,9 @@ public class Icons {
|
|||||||
static public final ImageIcon appIcon = new ImageIcon(Icons.class.getResource("icons/appIcon.png"));
|
static public final ImageIcon appIcon = new ImageIcon(Icons.class.getResource("icons/appIcon.png"));
|
||||||
static public final ImageIcon star = new ImageIcon(Icons.class.getResource("icons/star.png"));
|
static public final ImageIcon star = new ImageIcon(Icons.class.getResource("icons/star.png"));
|
||||||
static public final ImageIcon important = new ImageIcon(Icons.class.getResource("icons/important.png"));
|
static public final ImageIcon important = new ImageIcon(Icons.class.getResource("icons/important.png"));
|
||||||
|
static public final ImageIcon spinner0 = new ImageIcon(Icons.class.getResource("icons/spinner0.png"));
|
||||||
|
static public final ImageIcon spinner1 = new ImageIcon(Icons.class.getResource("icons/spinner1.png"));
|
||||||
|
static public final ImageIcon spinner2 = new ImageIcon(Icons.class.getResource("icons/spinner2.png"));
|
||||||
|
static public final ImageIcon spinner3 = new ImageIcon(Icons.class.getResource("icons/spinner3.png"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
try {
|
try {
|
||||||
AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, audioFile);
|
AudioSystem.write(inputStream, AudioFileFormat.Type.WAVE, audioFile);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
inputStream = null;
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,8 +113,10 @@ public class Sentence extends DefaultMutableTreeNode implements Cacheable {
|
|||||||
public void stopRecording() {
|
public void stopRecording() {
|
||||||
try {
|
try {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
|
inputStream = null;
|
||||||
line.stop();
|
line.stop();
|
||||||
line.close();
|
line.close();
|
||||||
|
line = null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user