From 57178fa35e09dc302107c77e73afc0c3676f0f40 Mon Sep 17 00:00:00 2001 From: mdb Date: Mon, 30 Oct 2000 22:21:11 +0000 Subject: [PATCH] Added encoder interface, fixed more stuff up. git-svn-id: https://samskivert.googlecode.com/svn/trunk@8 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../java/robodj/convert/CDParanoiaRipper.java | 90 ++++++++++++++----- .../convert/ConversionProgressListener.java | 22 +++++ .../java/robodj/convert/ConvertException.java | 17 ++++ .../src/java/robodj/convert/Encoder.java | 28 ++++++ .../src/java/robodj/convert/L3Encoder.java | 58 ++++++++++++ .../robodj/src/java/robodj/convert/Makefile | 7 +- .../src/java/robodj/convert/RipException.java | 16 ---- .../src/java/robodj/convert/RipTest.java | 4 +- .../src/java/robodj/convert/RipUtil.java | 4 +- .../src/java/robodj/convert/Ripper.java | 37 ++++++-- 10 files changed, 232 insertions(+), 51 deletions(-) create mode 100644 projects/robodj/src/java/robodj/convert/ConversionProgressListener.java create mode 100644 projects/robodj/src/java/robodj/convert/ConvertException.java create mode 100644 projects/robodj/src/java/robodj/convert/Encoder.java create mode 100644 projects/robodj/src/java/robodj/convert/L3Encoder.java delete mode 100644 projects/robodj/src/java/robodj/convert/RipException.java diff --git a/projects/robodj/src/java/robodj/convert/CDParanoiaRipper.java b/projects/robodj/src/java/robodj/convert/CDParanoiaRipper.java index eade5e1e..cfb53664 100644 --- a/projects/robodj/src/java/robodj/convert/CDParanoiaRipper.java +++ b/projects/robodj/src/java/robodj/convert/CDParanoiaRipper.java @@ -1,7 +1,7 @@ // -// $Id: CDParanoiaRipper.java,v 1.1 2000/10/30 21:08:53 mdb Exp $ +// $Id: CDParanoiaRipper.java,v 1.2 2000/10/30 22:21:11 mdb Exp $ -package robodj.rip; +package robodj.convert; import java.io.*; import java.util.ArrayList; @@ -13,8 +13,20 @@ import gnu.regexp.*; */ public class CDParanoiaRipper implements Ripper { - public TrackInfo[] getTrackInfo () throws RipException + public TrackInfo[] getTrackInfo () + throws ConvertException { + // an input line that we're interested in looks something like + // this: + // + // 1. 17980 [03:59.55] 0 [00:00.00] no no 2 + RE regex; + try { + regex = new RE("^\\s*\\d+\\.\\s+(\\d+)\\s\\[\\S*\\]\\s+(\\d+)"); + } catch (REException ree) { + throw new ConvertException("Can't compile regexp?! " + ree); + } + try { // fork off a cdparanoia process to read the TOC Runtime rt = Runtime.getRuntime(); @@ -28,13 +40,6 @@ public class CDParanoiaRipper implements Ripper StringBuffer input = new StringBuffer(); ArrayList flist = new ArrayList(); - // an input line that we're interested in looks something like - // this: - // - // 1. 17980 [03:59.55] 0 [00:00.00] no no 2 - RE regex = - new RE("^\\s*\\d+\\.\\s+(\\d+)\\s\\[\\S*\\]\\s+(\\d+)"); - while ((inline = din.readLine()) != null) { // skip blank lines and lines that are in the header if (inline.trim().length() == 0 || @@ -43,8 +48,6 @@ public class CDParanoiaRipper implements Ripper continue; } - // System.out.println("Matching: " + inline); - // keep track of all of the input in case we need to // report an error later input.append(inline).append("\n"); @@ -62,14 +65,14 @@ public class CDParanoiaRipper implements Ripper int retval = tocproc.waitFor(); if (retval != 0) { // ship off the error output from cdparanoia - throw new RipException(input.toString()); + throw new ConvertException(input.toString()); } } catch (InterruptedException ie) { // why we were interrupted I can only speculate, but we'll // go ahead and freak out anyway - throw new RipException("Interrupted while waiting for " + - "cdparanoia process to exit."); + throw new ConvertException("Interrupted while waiting for " + + "cdparanoia process to exit."); } // parse the frame offsets and stick them in an array @@ -88,20 +91,63 @@ public class CDParanoiaRipper implements Ripper frames[i].offset += 2 * RipUtil.FRAMES_PER_SECOND; } catch (NumberFormatException nfe) { - throw new RipException("Bogus frame value for track " + - (i+1) + ": " + nfe.getMessage() + - "\n\n" + input); + throw new ConvertException( + "Bogus frame value for track " + (i+1) + ": " + + nfe.getMessage() + "\n\n" + input); } } return frames; - } catch (REException ree) { - throw new RipException("Can't compile regular expression?! " + - ree); + } catch (IOException ioe) { + throw new ConvertException( + "Error communicating with ripper:\n" + ioe); + } + } + + public void ripTrack (int index, String target, + RipProgressListener listener) + throws ConvertException + { + StringBuffer cmd = new StringBuffer("cdparanoia"); + cmd.append(" -w"); // request output in WAV format + cmd.append(" -e"); // request progress information to stderr + cmd.append(" ").append(index); // add track number + cmd.append(" ").append(target); // add output file name + + try { + // fork off a cdparanoia process to read the TOC + Runtime rt = Runtime.getRuntime(); + Process ripproc = rt.exec(cmd.toString()); + + InputStream in = ripproc.getErrorStream(); + BufferedInputStream bin = new BufferedInputStream(in); + DataInputStream din = new DataInputStream(bin); + + // read output from the subprocess and chuck it for now + while (din.readLine() != null) { + // la la la + } + + // check the return value of the process + try { + int retval = ripproc.waitFor(); + if (retval != 0) { + // ship off the error output from cdparanoia + throw new ConvertException( + "Ripper failed: " + retval); + } + + } catch (InterruptedException ie) { + // why we were interrupted I can only speculate, but we'll + // go ahead and freak out anyway + throw new ConvertException("Interrupted while waiting for " + + "ripper process to exit."); + } } catch (IOException ioe) { - throw new RipException("Error talking to rip process: " + ioe); + throw new ConvertException( + "Error communicating with ripper:\n" + ioe); } } } diff --git a/projects/robodj/src/java/robodj/convert/ConversionProgressListener.java b/projects/robodj/src/java/robodj/convert/ConversionProgressListener.java new file mode 100644 index 00000000..db63705a --- /dev/null +++ b/projects/robodj/src/java/robodj/convert/ConversionProgressListener.java @@ -0,0 +1,22 @@ +// +// $Id: ConversionProgressListener.java,v 1.1 2000/10/30 22:21:11 mdb Exp $ + +package robodj.convert; + +/** + * This interface is used to communicate ripping progress from a ripper or + * encoder implementation to code using the conversion services (and + * hopefully ultimately to the end user). + */ +public interface ConversionProgressListener +{ + /** + * Informs the listener that the converter has completed the specified + * percentage of the conversion process. The percentage should reflect + * only the conversion being performed by the converter at that time + * (ripping or converting a single track). The information provided + * herein will be mapped to a global progress indication by the + * calling software (in the case of converting an entire CD). + */ + public void updateProgress (float percentComplete); +} diff --git a/projects/robodj/src/java/robodj/convert/ConvertException.java b/projects/robodj/src/java/robodj/convert/ConvertException.java new file mode 100644 index 00000000..30600b70 --- /dev/null +++ b/projects/robodj/src/java/robodj/convert/ConvertException.java @@ -0,0 +1,17 @@ +// +// $Id: ConvertException.java,v 1.1 2000/10/30 22:21:11 mdb Exp $ + +package robodj.convert; + +/** + * A convert exception can be thrown to indicate that some problem was + * encountered during some part of the conversion process (ripping or + * encoding). + */ +public class ConvertException extends Exception +{ + public ConvertException (String message) + { + super(message); + } +} diff --git a/projects/robodj/src/java/robodj/convert/Encoder.java b/projects/robodj/src/java/robodj/convert/Encoder.java new file mode 100644 index 00000000..1b21d44c --- /dev/null +++ b/projects/robodj/src/java/robodj/convert/Encoder.java @@ -0,0 +1,28 @@ +// +// $Id: Encoder.java,v 1.1 2000/10/30 22:21:11 mdb Exp $ + +package robodj.convert; + +/** + * The encoder interface is used to manipulate particular MP3 encoding + * software in the ways needed by the RoboDJ system. + */ +public interface Encoder +{ + /** + * Instructs the encoder to encode the specified track. + * + * @param source the path to the source file that should be encoded. + * @param dest the path to the destination file which should be + * created by the encoder. + * @param listener a callback object that should be called to + * communicate encoding progress. If the listener parameter is null, + * the caller doesn't want to hear about progress (shame on them). + * + * @exception ConvertException can be thrown if anything fails during + * the encoding process. + */ + public void encodeTrack (String source, String dest, + ConversionProgressListener listener) + throws ConvertException; +} diff --git a/projects/robodj/src/java/robodj/convert/L3Encoder.java b/projects/robodj/src/java/robodj/convert/L3Encoder.java new file mode 100644 index 00000000..121e9b59 --- /dev/null +++ b/projects/robodj/src/java/robodj/convert/L3Encoder.java @@ -0,0 +1,58 @@ +// +// $Id: L3Encoder.java,v 1.1 2000/10/30 22:21:11 mdb Exp $ + +package robodj.convert; + +import java.io.*; + +/** + * An encoder implementation that uses the Fraunhofer-IIS L3ENC mp3 + * encoding program. + */ +public class L3Encoder implements Encoder +{ + public void encodeTrack (String source, String dest, + ConversionProgressListener listener) + throws ConvertException + { + StringBuffer cmd = new StringBuffer("l3enc"); + cmd.append(" ").append(source); // add input file name + cmd.append(" ").append(dest); // add output file name + cmd.append(" -br 128000"); // request 128kbps encoding + + try { + // fork off a cdparanoia process to read the TOC + Runtime rt = Runtime.getRuntime(); + Process encproc = rt.exec(cmd.toString()); + + InputStream in = encproc.getErrorStream(); + BufferedInputStream bin = new BufferedInputStream(in); + DataInputStream din = new DataInputStream(bin); + + // read output from the subprocess and chuck it for now + while (din.readLine() != null) { + // la la la + } + + // check the return value of the process + try { + int retval = encproc.waitFor(); + if (retval != 0) { + // ship off the error output from cdparanoia + throw new ConvertException( + "Encoder failed: " + retval); + } + + } catch (InterruptedException ie) { + // why we were interrupted I can only speculate, but we'll + // go ahead and freak out anyway + throw new ConvertException("Interrupted while waiting for " + + "encoder process to exit."); + } + + } catch (IOException ioe) { + throw new ConvertException( + "Error communicating with encoder:\n" + ioe); + } + } +} diff --git a/projects/robodj/src/java/robodj/convert/Makefile b/projects/robodj/src/java/robodj/convert/Makefile index 4cb6a541..cd679f2d 100644 --- a/projects/robodj/src/java/robodj/convert/Makefile +++ b/projects/robodj/src/java/robodj/convert/Makefile @@ -1,11 +1,14 @@ # -# $Id: Makefile,v 1.1 2000/10/30 21:08:53 mdb Exp $ +# $Id: Makefile,v 1.2 2000/10/30 22:21:11 mdb Exp $ ROOT = ../.. SRCS = \ CDParanoiaRipper.java \ - RipException.java \ + ConversionProgressListener.java \ + ConvertException.java \ + Encoder.java \ + L3Encoder.java \ RipTest.java \ RipUtil.java \ Ripper.java \ diff --git a/projects/robodj/src/java/robodj/convert/RipException.java b/projects/robodj/src/java/robodj/convert/RipException.java deleted file mode 100644 index aa4a0fdd..00000000 --- a/projects/robodj/src/java/robodj/convert/RipException.java +++ /dev/null @@ -1,16 +0,0 @@ -// -// $Id: RipException.java,v 1.1 2000/10/30 21:08:53 mdb Exp $ - -package robodj.rip; - -/** - * A rip exception can be thrown to indicate that some problem was - * encountered during some part of the ripping process. - */ -public class RipException extends Exception -{ - public RipException (String message) - { - super(message); - } -} diff --git a/projects/robodj/src/java/robodj/convert/RipTest.java b/projects/robodj/src/java/robodj/convert/RipTest.java index 30d08b3f..01c8dc82 100644 --- a/projects/robodj/src/java/robodj/convert/RipTest.java +++ b/projects/robodj/src/java/robodj/convert/RipTest.java @@ -1,7 +1,7 @@ // -// $Id: RipTest.java,v 1.1 2000/10/30 21:08:53 mdb Exp $ +// $Id: RipTest.java,v 1.2 2000/10/30 22:21:11 mdb Exp $ -package robodj.rip; +package robodj.convert; import com.samskivert.net.cddb.*; diff --git a/projects/robodj/src/java/robodj/convert/RipUtil.java b/projects/robodj/src/java/robodj/convert/RipUtil.java index fe98d4e6..cf59dbd6 100644 --- a/projects/robodj/src/java/robodj/convert/RipUtil.java +++ b/projects/robodj/src/java/robodj/convert/RipUtil.java @@ -1,7 +1,7 @@ // -// $Id: RipUtil.java,v 1.1 2000/10/30 21:08:53 mdb Exp $ +// $Id: RipUtil.java,v 1.2 2000/10/30 22:21:11 mdb Exp $ -package robodj.rip; +package robodj.convert; /** * This class contains utility functions related to ripping. diff --git a/projects/robodj/src/java/robodj/convert/Ripper.java b/projects/robodj/src/java/robodj/convert/Ripper.java index ab2abfc8..53027275 100644 --- a/projects/robodj/src/java/robodj/convert/Ripper.java +++ b/projects/robodj/src/java/robodj/convert/Ripper.java @@ -1,11 +1,11 @@ // -// $Id: Ripper.java,v 1.1 2000/10/30 21:08:53 mdb Exp $ +// $Id: Ripper.java,v 1.2 2000/10/30 22:21:11 mdb Exp $ -package robodj.rip; +package robodj.convert; /** - * The ripper interface is used to manipulate a particular piece of CD - * ripping software in the ways needed by the RoboDJ system. + * The ripper interface is used to manipulate particular CD ripping + * software in the ways needed by the RoboDJ system. */ public interface Ripper { @@ -33,9 +33,32 @@ public interface Ripper * seconds to do its job or it will be declared delinquent and * ignored. * - * @exception RipException can be thrown if some problem occurs trying - * to read the CD table of contents (like lack of access to the CDROM + * @exception ConvertException can be thrown if some problem occurs + * trying to read the CD table of contents (like lack of access to the + * CDROM device or any other errors). + */ + public TrackInfo[] getTrackInfo () + throws ConvertException; + + /** + * Instructs the ripper to rip the track with the supplied index into + * the file specified by target. If the ripper supports progress + * notification, it should communicate it to the supplied progress + * listener. The track should be ripped in WAV format. + * + * @param index the track number of the track to rip (starting at 1 + * since CDs start counting tracks at 1). + * @param target the path to the file into which the track should be + * ripped. + * @param listener a callback object that should be called to + * communicate ripping progress. If the listener parameter is null, + * the caller doesn't want to hear about progress (shame on them). + * + * @exception ConvertException can be thrown if some problem occurs + * trying to rip the specified track (like lack of access to the CDROM * device or any other errors). */ - public TrackInfo[] getTrackInfo () throws RipException; + public void ripTrack (int index, String target, + ConversionProgressListener listener) + throws ConvertException; }