Finished up the importer and fixed various things along the way.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@101 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -0,0 +1 @@
|
||||
extern
|
||||
@@ -52,7 +52,7 @@ if (defined $libpath) {
|
||||
}
|
||||
|
||||
# put everything in our class path
|
||||
my $classpath = "-classpath $jlib:$root/src/java";
|
||||
my $classpath = "-classpath $jlib:$root/dist/classes";
|
||||
|
||||
# any zip or jar files in our lib/ directory get added to the class path
|
||||
if (opendir(DIR, "$root/lib")) {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<!-- build configuration -->
|
||||
<project name="robodj" default="compile" basedir=".">
|
||||
|
||||
<!-- configuration parameters -->
|
||||
<property name="app.name" value="robodj"/>
|
||||
<property name="deploy.home" value="dist"/>
|
||||
<property name="dist.home" value="${deploy.home}"/>
|
||||
<property name="dist.jar" value="${app.name}.jar"/>
|
||||
<property name="javadoc.home" value="${deploy.home}/docs"/>
|
||||
<property name="build.compiler" value="jikes"/>
|
||||
<property name="java.libraries" value="/usr/share/java"/>
|
||||
|
||||
<!-- prepares the application directories -->
|
||||
<target name="prepare">
|
||||
<mkdir dir="${deploy.home}"/>
|
||||
<mkdir dir="${deploy.home}/classes"/>
|
||||
<mkdir dir="${javadoc.home}"/>
|
||||
<!-- copy media into the target directory -->
|
||||
<copy todir="${deploy.home}/classes">
|
||||
<fileset dir="src/java" includes="**/*.gif"/>
|
||||
<fileset dir="src/java" includes="**/*.jpg"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- cleans out the installed application -->
|
||||
<target name="clean">
|
||||
<delete dir="${deploy.home}"/>
|
||||
</target>
|
||||
|
||||
<!-- build the java class files -->
|
||||
<target name="compile" depends="prepare">
|
||||
<javac srcdir="src/java" destdir="${deploy.home}/classes"
|
||||
debug="on" optimize="off" deprecation="off">
|
||||
<classpath>
|
||||
<fileset dir="${java.libraries}" includes="**/*.jar"/>
|
||||
<fileset dir="lib" includes="**/*.jar"/>
|
||||
<pathelement location="${deploy.home}/classes"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- build the javadoc documentation -->
|
||||
<target name="javadoc" depends="prepare">
|
||||
<javadoc sourcepath="src/java"
|
||||
packagenames="robodj.*"
|
||||
classpath="${deploy.home}/classes"
|
||||
destdir="${javadoc.home}"/>
|
||||
</target>
|
||||
|
||||
<!-- the default target is to rebuild everything -->
|
||||
<target name="all" depends="clean,prepare,compile,javadoc"/>
|
||||
|
||||
<!-- builds our distribution files (war and jar) -->
|
||||
<target name="dist" depends="prepare,compile">
|
||||
<jar jarfile="${dist.home}/${dist.jar}"
|
||||
basedir="${deploy.home}/classes"/>
|
||||
</target>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
RoboDJ Notes
|
||||
------------
|
||||
|
||||
- Catch database errors after the ripping process and allow use to retry
|
||||
commit to database after fixing database unavailability.
|
||||
|
||||
- Impersonate a registered CDDB client until we can get "approval".
|
||||
@@ -0,0 +1 @@
|
||||
*.jar
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// $Id: Log.java,v 1.1 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj;
|
||||
|
||||
/**
|
||||
* A placeholder class that contains a reference to the log object used by
|
||||
* the robodj package.
|
||||
*/
|
||||
public class Log
|
||||
{
|
||||
public static com.samskivert.util.Log log =
|
||||
new com.samskivert.util.Log("robodj");
|
||||
|
||||
/** Convenience function. */
|
||||
public static void debug (String message)
|
||||
{
|
||||
log.debug(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void info (String message)
|
||||
{
|
||||
log.info(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void warning (String message)
|
||||
{
|
||||
log.warning(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void logStackTrace (Throwable t)
|
||||
{
|
||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// $Id: EncodeTest.java,v 1.1 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.convert;
|
||||
|
||||
import com.samskivert.net.cddb.*;
|
||||
|
||||
public class EncodeTest
|
||||
{
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length < 2) {
|
||||
System.err.println("Usage: EncodeTest source.wav dest.mp3");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
try {
|
||||
Encoder encoder = new LameEncoder();
|
||||
ConversionProgressListener listener =
|
||||
new ConversionProgressListener() {
|
||||
public void updateProgress (int percentDone)
|
||||
{
|
||||
System.out.println("Percent done: " +
|
||||
percentDone + "%");
|
||||
}
|
||||
};
|
||||
encoder.encodeTrack(args[0], args[1], listener);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// $Id: LameEncoder.java,v 1.1 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.convert;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import gnu.regexp.*;
|
||||
|
||||
/**
|
||||
* An encoder implementation that uses LAME to do it's job.
|
||||
*/
|
||||
public class LameEncoder implements Encoder
|
||||
{
|
||||
public void encodeTrack (String source, String dest,
|
||||
ConversionProgressListener listener)
|
||||
throws ConvertException
|
||||
{
|
||||
StringBuffer cmd = new StringBuffer("lame");
|
||||
cmd.append(" --nohist"); // we don't want histogram output
|
||||
cmd.append(" -v"); // request variable bitrate encoding
|
||||
cmd.append(" ").append(source); // add source file name
|
||||
cmd.append(" ").append(dest); // add output file name
|
||||
|
||||
// we'll need this for later
|
||||
RE regex;
|
||||
try {
|
||||
// a line of input looks like this
|
||||
// 0/1273 ( 0%)| 0:00/ 0:00...
|
||||
regex = new RE("^\\s*(\\d+)/(\\d+)\\s*\\(.*");
|
||||
} 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();
|
||||
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
|
||||
String out;
|
||||
int lastReported = 0;
|
||||
|
||||
while ((out = din.readLine()) != null) {
|
||||
// if they don't care about the output then neither do we
|
||||
if (listener == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse the output
|
||||
REMatch match = regex.getMatch(out);
|
||||
if (match != null) {
|
||||
int offset = -1, total = -1;
|
||||
try {
|
||||
offset = Integer.parseInt(match.toString(1));
|
||||
total = Integer.parseInt(match.toString(2));
|
||||
} catch (NumberFormatException nfe) {
|
||||
System.err.println("Malformed position info: " + out);
|
||||
continue;
|
||||
}
|
||||
|
||||
int pctDone = (100 * offset) / total;
|
||||
if (pctDone - lastReported >= 1) {
|
||||
listener.updateProgress(pctDone);
|
||||
lastReported = pctDone;
|
||||
}
|
||||
|
||||
} else {
|
||||
// System.out.println("Couldn't match: " + out);
|
||||
}
|
||||
}
|
||||
|
||||
// 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(
|
||||
"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.");
|
||||
}
|
||||
|
||||
// if everything was successful, report completion
|
||||
if (lastReported < 100) {
|
||||
listener.updateProgress(100);
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
throw new ConvertException(
|
||||
"Error communicating with encoder:\n" + ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: RipTest.java,v 1.3 2001/02/06 08:18:00 mdb Exp $
|
||||
// $Id: RipTest.java,v 1.4 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.convert;
|
||||
|
||||
@@ -24,6 +24,7 @@ public class RipTest
|
||||
int length = RipUtil.computeDiscLength(info);
|
||||
|
||||
try {
|
||||
System.out.println("connecting to: " + hostname);
|
||||
String rsp = cddb.connect(hostname);
|
||||
|
||||
// set the timeout to 30 seconds
|
||||
@@ -80,7 +81,7 @@ public class RipTest
|
||||
|
||||
} else {
|
||||
// try the CDDB lookup
|
||||
lookupCDDB("us.cddb.com", info);
|
||||
lookupCDDB("ca.freedb.org", info);
|
||||
|
||||
// rip a track, for fun
|
||||
int track = 2;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: CDDBLookupPanel.java,v 1.1 2000/12/10 07:02:09 mdb Exp $
|
||||
// $Id: CDDBLookupPanel.java,v 1.2 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.importer;
|
||||
|
||||
@@ -34,11 +34,24 @@ public class CDDBLookupPanel
|
||||
cdlabel.setFont(new Font("Helvetica", Font.BOLD, 24));
|
||||
add(cdlabel, GroupLayout.FIXED);
|
||||
|
||||
// on the right hand side we want a status display to let the user
|
||||
// know how the CDDB lookup process is going
|
||||
GroupLayout vgl = new VGroupLayout(GroupLayout.STRETCH);
|
||||
vgl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||
_spanel = new JPanel(vgl);
|
||||
|
||||
JLabel sl = new JLabel("Status", JLabel.LEFT);
|
||||
_spanel.add(sl, GroupLayout.FIXED);
|
||||
|
||||
// create the "insert cd" text label for the right hand side
|
||||
_infoText = new JTextArea("Reading CD information...");
|
||||
_infoText.setLineWrap(true);
|
||||
_infoText.setEditable(false);
|
||||
add(_infoText);
|
||||
// make something for it to scroll around in
|
||||
_spanel.add(new JScrollPane(_infoText));
|
||||
|
||||
// add our panel to the main group
|
||||
add(_spanel);
|
||||
}
|
||||
|
||||
public void wasAddedToFrame (ImporterFrame frame)
|
||||
@@ -82,7 +95,7 @@ public class CDDBLookupPanel
|
||||
public Object invoke ()
|
||||
throws Exception
|
||||
{
|
||||
return CDDBUtil.doCDDBLookup("us.cddb.com", info);
|
||||
return CDDBUtil.doCDDBLookup("ca.freedb.org", info);
|
||||
}
|
||||
|
||||
public boolean abort ()
|
||||
@@ -97,7 +110,7 @@ public class CDDBLookupPanel
|
||||
CDDB.Detail[] details = (CDDB.Detail[])result;
|
||||
|
||||
// replace the info text with the CD info editor
|
||||
remove(_infoText);
|
||||
remove(_spanel);
|
||||
_infoEditor = new CDInfoEditor(details, _info.length);
|
||||
add(_infoEditor);
|
||||
|
||||
@@ -179,6 +192,7 @@ public class CDDBLookupPanel
|
||||
|
||||
protected ImporterFrame _frame;
|
||||
protected JButton _next;
|
||||
protected JPanel _spanel;
|
||||
protected JTextArea _infoText;
|
||||
protected CDInfoEditor _infoEditor;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: CDInfoEditor.java,v 1.1 2000/12/10 07:02:09 mdb Exp $
|
||||
// $Id: CDInfoEditor.java,v 1.2 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.importer;
|
||||
|
||||
@@ -26,10 +26,11 @@ public class CDInfoEditor
|
||||
JLabel selLabel = new JLabel("Select...");
|
||||
|
||||
// create a string array for our combo box
|
||||
String[] names = new String[details.length];
|
||||
String[] names = new String[details.length + 1];
|
||||
for (int i = 0; i < details.length; i++) {
|
||||
names[i] = details[i].title;
|
||||
}
|
||||
names[details.length] = "<blank>";
|
||||
|
||||
_selBox = new JComboBox(names);
|
||||
selPanel.add(selLabel, GroupLayout.FIXED);
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
//
|
||||
// $Id: Importer.java,v 1.1 2000/12/10 07:02:09 mdb Exp $
|
||||
// $Id: Importer.java,v 1.2 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.importer;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.samskivert.util.Log;
|
||||
import com.samskivert.util.PropertiesUtil;
|
||||
|
||||
import robodj.repository.Repository;
|
||||
|
||||
/**
|
||||
* The importer is the GUI-based application for ripping, encoding and
|
||||
@@ -11,10 +17,40 @@ import com.samskivert.util.Log;
|
||||
*/
|
||||
public class Importer
|
||||
{
|
||||
/**
|
||||
* This is the string we use for the source field of entries created
|
||||
* by the importer.
|
||||
*/
|
||||
public static final String ENTRY_SOURCE = "CD";
|
||||
|
||||
public static Log log = new Log("importer");
|
||||
|
||||
public static Properties config;
|
||||
|
||||
public static Repository repository;
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
// set up our configuration by hand for now
|
||||
config = new Properties();
|
||||
config.setProperty("repository.db.driver", "org.gjt.mm.mysql.Driver");
|
||||
config.setProperty("repository.db.username", "www");
|
||||
config.setProperty("repository.db.password", "Il0ve2PL@Y");
|
||||
config.setProperty("repository.db.url",
|
||||
"jdbc:mysql://depravity:3306/robodj");
|
||||
config.setProperty("repository.basedir", "/export/robodj/repository");
|
||||
|
||||
// create an interface to the database repository
|
||||
try {
|
||||
Properties dbprops =
|
||||
PropertiesUtil.getSubProperties(config, "repository.db");
|
||||
repository = new Repository(dbprops);
|
||||
} catch (SQLException sqe) {
|
||||
System.err.println("Unable to establish communication " +
|
||||
"with music database: " + sqe);
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
ImporterFrame frame = new ImporterFrame();
|
||||
InsertCDPanel panel = new InsertCDPanel();
|
||||
frame.setPanel(panel);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: ImporterFrame.java,v 1.1 2000/12/10 07:02:09 mdb Exp $
|
||||
// $Id: ImporterFrame.java,v 1.2 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.importer;
|
||||
|
||||
@@ -24,7 +24,9 @@ public class ImporterFrame extends JFrame
|
||||
_top.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||
|
||||
// create a container for our control buttons
|
||||
_buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
GroupLayout bgl = new HGroupLayout(GroupLayout.NONE);
|
||||
bgl.setJustification(GroupLayout.RIGHT);
|
||||
_buttonPanel = new JPanel(bgl);
|
||||
|
||||
// stick it into the frame
|
||||
_top.add(_buttonPanel, GroupLayout.FIXED);
|
||||
@@ -51,7 +53,6 @@ public class ImporterFrame extends JFrame
|
||||
// then stick the new panel in there
|
||||
if (panel != null) {
|
||||
_panel = panel;
|
||||
_panel.setBackground(Color.yellow);
|
||||
_top.add(_panel, 0);
|
||||
// let the panel know that it was added
|
||||
_panel.wasAddedToFrame(this);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
//
|
||||
// $Id: Panel.java,v 1.1 2000/12/10 07:02:09 mdb Exp $
|
||||
// $Id: Panel.java,v 1.2 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.importer;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class Panel extends JPanel
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
//
|
||||
// $Id: RipPanel.java,v 1.1 2000/12/10 07:02:09 mdb Exp $
|
||||
// $Id: RipPanel.java,v 1.2 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.importer;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -16,6 +17,7 @@ import com.samskivert.swing.util.*;
|
||||
import com.samskivert.swing.*;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import robodj.Log;
|
||||
import robodj.convert.*;
|
||||
import robodj.repository.*;
|
||||
|
||||
@@ -30,39 +32,324 @@ public class RipPanel
|
||||
setLayout(gl);
|
||||
|
||||
// create our label for the left hand side
|
||||
JLabel cdlabel = new JLabel("Ripping", JLabel.CENTER);
|
||||
JLabel cdlabel = new JLabel("Converting", JLabel.CENTER);
|
||||
cdlabel.setFont(new Font("Helvetica", Font.BOLD, 24));
|
||||
add(cdlabel, GroupLayout.FIXED);
|
||||
|
||||
// create a panel for the progress display
|
||||
GroupLayout vgl = new VGroupLayout(GroupLayout.STRETCH);
|
||||
vgl.setOffAxisPolicy(GroupLayout.STRETCH);
|
||||
JPanel ppanel = new JPanel(vgl);
|
||||
|
||||
// create the overall progress indicator
|
||||
JLabel opl = new JLabel("Overall progress", JLabel.LEFT);
|
||||
ppanel.add(opl, GroupLayout.FIXED);
|
||||
// overall progress assumes equal time spent ripping and encoding
|
||||
// each track on the disc. not entirely accurate, but reasonable
|
||||
// for giving a general idea of how far along we are
|
||||
_oprogress = new JProgressBar(0, 200*info.length);
|
||||
ppanel.add(_oprogress, GroupLayout.FIXED);
|
||||
|
||||
// create the task progress indicator
|
||||
JLabel tpl = new JLabel("Track progress", JLabel.LEFT);
|
||||
ppanel.add(tpl, GroupLayout.FIXED);
|
||||
_progress = new JProgressBar(0, 100);
|
||||
ppanel.add(_progress, GroupLayout.FIXED);
|
||||
|
||||
// create the status log
|
||||
JLabel sl = new JLabel("Status", JLabel.LEFT);
|
||||
ppanel.add(sl, GroupLayout.FIXED);
|
||||
_statusLog = new JTextArea();
|
||||
_statusLog.setLineWrap(true);
|
||||
_statusLog.setEditable(false);
|
||||
// make something for it to scroll around in
|
||||
ppanel.add(new JScrollPane(_statusLog));
|
||||
|
||||
// add our panel to the main group
|
||||
add(ppanel);
|
||||
|
||||
// save this stuff for later
|
||||
_info = info;
|
||||
_entry = entry;
|
||||
}
|
||||
|
||||
protected void postAsyncStatus (final String status)
|
||||
{
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run ()
|
||||
{
|
||||
_statusLog.append(status + "\n");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void postAsyncProgress (final int overallComplete,
|
||||
final int taskComplete)
|
||||
{
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run ()
|
||||
{
|
||||
// update our progress indicators
|
||||
_oprogress.setValue(overallComplete);
|
||||
_progress.setValue(taskComplete);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static String createTempPath (int trackno, String ext)
|
||||
{
|
||||
return "/tmp/track" + trackno + "." + ext;
|
||||
}
|
||||
|
||||
/** Handles the ripping and encoding of the tracks. */
|
||||
protected class RipperTask
|
||||
implements Task, ConversionProgressListener
|
||||
{
|
||||
public RipperTask (Ripper.TrackInfo[] info)
|
||||
{
|
||||
_info = info;
|
||||
}
|
||||
|
||||
public Object invoke ()
|
||||
throws Exception
|
||||
{
|
||||
Ripper ripper = new CDParanoiaRipper();
|
||||
Encoder encoder = new LameEncoder();
|
||||
|
||||
for (int i = 0; i < _info.length; i++) {
|
||||
_track = i+1;
|
||||
|
||||
// rip the track
|
||||
_encoding = false;
|
||||
// it takes a second or so for the ripper to start
|
||||
// reporting progress, so we clear out the progress
|
||||
// indicator so that the 100% progress of the previous
|
||||
// track doesn't look like it applies to this new track
|
||||
// while we're spinning up
|
||||
updateProgress(0);
|
||||
postAsyncStatus("Ripping track " + _track + "...");
|
||||
String tpath = createTempPath(_track, "wav");
|
||||
ripper.ripTrack(_info, _track, tpath, this);
|
||||
|
||||
// then encode it
|
||||
_encoding = true;
|
||||
updateProgress(0);
|
||||
postAsyncStatus("Encoding track " + _track + "...");
|
||||
String dpath = createTempPath(_track, "mp3");
|
||||
encoder.encodeTrack(tpath, dpath, this);
|
||||
|
||||
// remove the source wav file
|
||||
File tfile = new File(tpath);
|
||||
if (!tfile.delete()) {
|
||||
postAsyncStatus("Unable to remove temp file " +
|
||||
"for track " + _track + ".");
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean abort ()
|
||||
{
|
||||
// no abort presently
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateProgress (int percentComplete)
|
||||
{
|
||||
// first add completeness for tracks we've already done
|
||||
int overallComplete = (_track-1) * 200;
|
||||
// if we're encoding, then we finished ripping this track
|
||||
if (_encoding) {
|
||||
overallComplete += 100;
|
||||
}
|
||||
// finally add the percent complete for the current task
|
||||
overallComplete += percentComplete;
|
||||
// and pass it all on to the UI for display
|
||||
postAsyncProgress(overallComplete, percentComplete);
|
||||
}
|
||||
|
||||
protected Ripper.TrackInfo[] _info;
|
||||
protected int _track;
|
||||
protected boolean _encoding;
|
||||
}
|
||||
|
||||
/** Commits the completed entry into the repository. */
|
||||
protected class CommitterTask
|
||||
implements Task
|
||||
{
|
||||
public CommitterTask (Entry entry, Ripper.TrackInfo[] info)
|
||||
{
|
||||
_entry = entry;
|
||||
_info = info;
|
||||
}
|
||||
|
||||
public Object invoke ()
|
||||
throws Exception
|
||||
{
|
||||
int entryid = -1;
|
||||
|
||||
try {
|
||||
// determine the target directory for the mp3 files
|
||||
String rbase =
|
||||
Importer.config.getProperty("repository.basedir");
|
||||
if (StringUtil.blank(rbase)) {
|
||||
throw new Exception("No mp3 repository directory " +
|
||||
"specified.");
|
||||
}
|
||||
|
||||
// ensure the repository directory exists
|
||||
File rbf = new File(rbase);
|
||||
if (!rbf.exists() || !rbf.isDirectory()) {
|
||||
throw new Exception("Repository base directory '" +
|
||||
rbase + "' is not valid.");
|
||||
}
|
||||
|
||||
postAsyncStatus("Creating repository directory.");
|
||||
// create the hash directory
|
||||
int hcode = _entry.title.hashCode();
|
||||
if (hcode < 0) {
|
||||
hcode *= -1;
|
||||
}
|
||||
System.out.println(Integer.toHexString(255 % 0xFF));
|
||||
String hash = Integer.toHexString(hcode % 0xFF);
|
||||
StringBuffer tpath = new StringBuffer(rbase);
|
||||
if (tpath.charAt(tpath.length()-1) != '/') {
|
||||
tpath.append("/");
|
||||
}
|
||||
tpath.append(hash);
|
||||
|
||||
File tdir = new File(tpath.toString());
|
||||
if (!tdir.exists()) {
|
||||
if (!tdir.mkdir()) {
|
||||
throw new Exception("Unable to create target " +
|
||||
"directory: " + tpath);
|
||||
}
|
||||
|
||||
} else {
|
||||
// make sure it's a directory
|
||||
if (!tdir.isDirectory()) {
|
||||
throw new Exception("Target directory '" + tpath +
|
||||
"' is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
// fill in the entry source since we ripped this from CD
|
||||
_entry.source = Importer.ENTRY_SOURCE;
|
||||
|
||||
// fill in blanks for the locations of the tunes because
|
||||
// we won't know the name of the directory until we are
|
||||
// assigned an entry id
|
||||
for (int i = 0; i < _entry.songs.length; i++) {
|
||||
_entry.songs[i].location = "";
|
||||
}
|
||||
|
||||
postAsyncStatus("Creating database entry.");
|
||||
// insert the entry into the repository so that we get the
|
||||
// proper entry id which we'll need to put the tracks in their
|
||||
// proper place in the repository
|
||||
Importer.repository.insertEntry(_entry);
|
||||
// track this so that we can clean up in case of failure
|
||||
entryid = _entry.entryid;
|
||||
|
||||
// now that we have an entry id, fully construct the
|
||||
// target path
|
||||
tpath.append("/").append(_entry.entryid);
|
||||
tdir = new File(tpath.toString());
|
||||
if (!tdir.mkdir()) {
|
||||
throw new Exception("Unable to create target " +
|
||||
"directory: " + tpath);
|
||||
}
|
||||
|
||||
postAsyncStatus("Moving tracks into repository directory.");
|
||||
// move the tracks into the target directory
|
||||
tpath.append("/");
|
||||
for (int i = 0; i < _entry.songs.length; i++) {
|
||||
int tno = i+1;
|
||||
|
||||
// figure out the necessary paths
|
||||
String npath = tpath.toString() + tno + ".mp3";
|
||||
String opath = createTempPath(tno, "mp3");
|
||||
|
||||
// move the file
|
||||
File ofile = new File(opath);
|
||||
File nfile = new File(npath);
|
||||
if (!ofile.renameTo(nfile)) {
|
||||
throw new Exception("Unable to move track " + tno +
|
||||
" to target location: " + npath);
|
||||
}
|
||||
|
||||
// and update the song object
|
||||
_entry.songs[i].location = npath;
|
||||
}
|
||||
|
||||
// finally update the entry in the database
|
||||
Importer.repository.updateEntry(_entry);
|
||||
// and clear out the entryid to indicate success
|
||||
entryid = -1;
|
||||
|
||||
postAsyncStatus("Import complete.");
|
||||
return null;
|
||||
|
||||
} finally {
|
||||
// if we got halfway through creating our entry, remove it
|
||||
// from the database
|
||||
if (entryid != -1) {
|
||||
Importer.repository.deleteEntry(_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean abort ()
|
||||
{
|
||||
// we don't support aborting. this shouldn't take long at all
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Entry _entry;
|
||||
protected Ripper.TrackInfo[] _info;
|
||||
}
|
||||
|
||||
public void wasAddedToFrame (ImporterFrame frame)
|
||||
{
|
||||
// keep this for later
|
||||
_frame = frame;
|
||||
|
||||
frame.addControlButton("Cancel", "cancel", this);
|
||||
// add our next and cancel buttons
|
||||
_cancel = frame.addControlButton("Cancel", "cancel", this);
|
||||
_next = frame.addControlButton("Next...", "next", this);
|
||||
_next.setEnabled(false);
|
||||
|
||||
// create our info task and set it a running
|
||||
Task ripTask = new RipperTask(_info);
|
||||
TaskMaster.invokeTask("convert", ripTask, this);
|
||||
}
|
||||
|
||||
public void taskCompleted (String name, Object result)
|
||||
{
|
||||
if (name.equals("getinfo")) {
|
||||
if (name.equals("convert")) {
|
||||
// yay! we're all done. commit the entry to the repository
|
||||
Task commitTask = new CommitterTask(_entry, _info);
|
||||
TaskMaster.invokeTask("commit", commitTask, this);
|
||||
|
||||
} else if (name.equals("cddb_lookup")) {
|
||||
} else if (name.equals("commit")) {
|
||||
// we're all done. fix up the buttons and call it good
|
||||
_cancel.setEnabled(false);
|
||||
_next.setLabel("Exit");
|
||||
_next.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void taskFailed (String name, Throwable exception)
|
||||
{
|
||||
if (name.equals("getinfo")) {
|
||||
|
||||
} else if (name.equals("cddb_lookup")) {
|
||||
String msg;
|
||||
if (Exception.class.equals(exception.getClass())) {
|
||||
msg = exception.getMessage();
|
||||
} else {
|
||||
msg = exception.toString();
|
||||
}
|
||||
_statusLog.append("Error: " + msg + "\n");
|
||||
Log.logStackTrace(exception);
|
||||
}
|
||||
|
||||
public void actionPerformed (ActionEvent e)
|
||||
@@ -72,6 +359,7 @@ public class RipPanel
|
||||
System.exit(0);
|
||||
|
||||
} else if (cmd.equals("next")) {
|
||||
System.exit(0);
|
||||
|
||||
} else {
|
||||
System.out.println("Unknown action event: " + cmd);
|
||||
@@ -80,6 +368,12 @@ public class RipPanel
|
||||
|
||||
protected ImporterFrame _frame;
|
||||
protected JButton _next;
|
||||
protected JButton _cancel;
|
||||
protected JLabel _actionLabel;
|
||||
|
||||
protected JProgressBar _oprogress;
|
||||
protected JProgressBar _progress;
|
||||
protected JTextArea _statusLog;
|
||||
|
||||
protected Ripper.TrackInfo[] _info;
|
||||
protected Entry _entry;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Repository.java,v 1.2 2001/02/13 05:48:29 mdb Exp $
|
||||
// $Id: Repository.java,v 1.3 2001/03/18 06:58:55 mdb Exp $
|
||||
|
||||
package robodj.repository;
|
||||
|
||||
@@ -91,10 +91,12 @@ public class Repository extends MySQLRepository
|
||||
* and the song objects) will be filled in with the entryid of the
|
||||
* newly created entry.
|
||||
*/
|
||||
public void insertEntry (Entry entry)
|
||||
public void insertEntry (final Entry entry)
|
||||
throws SQLException
|
||||
{
|
||||
try {
|
||||
execute(new Operation () {
|
||||
public void invoke () throws SQLException
|
||||
{
|
||||
// insert the entry into the entry table
|
||||
_etable.insert(entry);
|
||||
|
||||
@@ -111,19 +113,8 @@ public class Repository extends MySQLRepository
|
||||
entry.songs[i].songid = lastInsertedId();
|
||||
}
|
||||
}
|
||||
|
||||
_session.commit();
|
||||
|
||||
} catch (SQLException sqe) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw sqe;
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw rte;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,10 +127,12 @@ public class Repository extends MySQLRepository
|
||||
* @see addSongToEntry
|
||||
* @see removeSongFromEntry
|
||||
*/
|
||||
public void updateEntry (Entry entry)
|
||||
public void updateEntry (final Entry entry)
|
||||
throws SQLException
|
||||
{
|
||||
try {
|
||||
execute(new Operation () {
|
||||
public void invoke () throws SQLException
|
||||
{
|
||||
// update the entry
|
||||
_etable.update(entry);
|
||||
|
||||
@@ -149,44 +142,25 @@ public class Repository extends MySQLRepository
|
||||
_stable.update(entry.songs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
_session.commit();
|
||||
|
||||
} catch (SQLException sqe) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw sqe;
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw rte;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the entry (and all associated songs) from the database.
|
||||
*/
|
||||
public void deleteEntry (Entry entry)
|
||||
public void deleteEntry (final Entry entry)
|
||||
throws SQLException
|
||||
{
|
||||
try {
|
||||
// remove the entry from the entry table and the foreign key
|
||||
// constraints will automatically remove all of the
|
||||
execute(new Operation () {
|
||||
public void invoke () throws SQLException
|
||||
{
|
||||
// remove the entry from the entry table and the foreign
|
||||
// key constraints will automatically remove all of the
|
||||
// corresponding songs
|
||||
_etable.delete(entry);
|
||||
_session.commit();
|
||||
|
||||
} catch (SQLException sqe) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw sqe;
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw rte;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,10 +175,12 @@ public class Repository extends MySQLRepository
|
||||
*
|
||||
* @see updateSong
|
||||
*/
|
||||
public void addSongToEntry (Entry entry, Song song)
|
||||
public void addSongToEntry (final Entry entry, final Song song)
|
||||
throws SQLException
|
||||
{
|
||||
try {
|
||||
execute(new Operation () {
|
||||
public void invoke () throws SQLException
|
||||
{
|
||||
// fill in the appropriate entry id value
|
||||
song.entryid = entry.entryid;
|
||||
|
||||
@@ -212,70 +188,42 @@ public class Repository extends MySQLRepository
|
||||
_stable.insert(song);
|
||||
// communicate the songid back to the caller
|
||||
song.songid = lastInsertedId();
|
||||
_session.commit();
|
||||
|
||||
} catch (SQLException sqe) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw sqe;
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw rte;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the specified song individually. The songid and entryid
|
||||
* parameters should already be set to the appropriate values.
|
||||
*/
|
||||
public void updateSong (Song song)
|
||||
public void updateSong (final Song song)
|
||||
throws SQLException
|
||||
{
|
||||
try {
|
||||
execute(new Operation () {
|
||||
public void invoke () throws SQLException
|
||||
{
|
||||
_stable.update(song);
|
||||
_session.commit();
|
||||
|
||||
} catch (SQLException sqe) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw sqe;
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw rte;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a category with the specified name and returns the id of
|
||||
* that new category.
|
||||
*/
|
||||
public int createCategory (String name)
|
||||
public int createCategory (final String name)
|
||||
throws SQLException
|
||||
{
|
||||
try {
|
||||
execute(new Operation () {
|
||||
public void invoke () throws SQLException
|
||||
{
|
||||
Category cat = new Category();
|
||||
cat.name = name;
|
||||
_ctable.insert(cat);
|
||||
|
||||
int categoryid = lastInsertedId();
|
||||
_session.commit();
|
||||
|
||||
return categoryid;
|
||||
|
||||
} catch (SQLException sqe) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw sqe;
|
||||
|
||||
} catch (RuntimeException rte) {
|
||||
// back out our changes if something got hosed
|
||||
_session.rollback();
|
||||
throw rte;
|
||||
}
|
||||
});
|
||||
|
||||
return lastInsertedId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user