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
|
# 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
|
# any zip or jar files in our lib/ directory get added to the class path
|
||||||
if (opendir(DIR, "$root/lib")) {
|
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;
|
package robodj.convert;
|
||||||
|
|
||||||
@@ -24,6 +24,7 @@ public class RipTest
|
|||||||
int length = RipUtil.computeDiscLength(info);
|
int length = RipUtil.computeDiscLength(info);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
System.out.println("connecting to: " + hostname);
|
||||||
String rsp = cddb.connect(hostname);
|
String rsp = cddb.connect(hostname);
|
||||||
|
|
||||||
// set the timeout to 30 seconds
|
// set the timeout to 30 seconds
|
||||||
@@ -80,7 +81,7 @@ public class RipTest
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// try the CDDB lookup
|
// try the CDDB lookup
|
||||||
lookupCDDB("us.cddb.com", info);
|
lookupCDDB("ca.freedb.org", info);
|
||||||
|
|
||||||
// rip a track, for fun
|
// rip a track, for fun
|
||||||
int track = 2;
|
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;
|
package robodj.importer;
|
||||||
|
|
||||||
@@ -34,11 +34,24 @@ public class CDDBLookupPanel
|
|||||||
cdlabel.setFont(new Font("Helvetica", Font.BOLD, 24));
|
cdlabel.setFont(new Font("Helvetica", Font.BOLD, 24));
|
||||||
add(cdlabel, GroupLayout.FIXED);
|
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
|
// create the "insert cd" text label for the right hand side
|
||||||
_infoText = new JTextArea("Reading CD information...");
|
_infoText = new JTextArea("Reading CD information...");
|
||||||
_infoText.setLineWrap(true);
|
_infoText.setLineWrap(true);
|
||||||
_infoText.setEditable(false);
|
_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)
|
public void wasAddedToFrame (ImporterFrame frame)
|
||||||
@@ -82,7 +95,7 @@ public class CDDBLookupPanel
|
|||||||
public Object invoke ()
|
public Object invoke ()
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
return CDDBUtil.doCDDBLookup("us.cddb.com", info);
|
return CDDBUtil.doCDDBLookup("ca.freedb.org", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean abort ()
|
public boolean abort ()
|
||||||
@@ -97,7 +110,7 @@ public class CDDBLookupPanel
|
|||||||
CDDB.Detail[] details = (CDDB.Detail[])result;
|
CDDB.Detail[] details = (CDDB.Detail[])result;
|
||||||
|
|
||||||
// replace the info text with the CD info editor
|
// replace the info text with the CD info editor
|
||||||
remove(_infoText);
|
remove(_spanel);
|
||||||
_infoEditor = new CDInfoEditor(details, _info.length);
|
_infoEditor = new CDInfoEditor(details, _info.length);
|
||||||
add(_infoEditor);
|
add(_infoEditor);
|
||||||
|
|
||||||
@@ -179,6 +192,7 @@ public class CDDBLookupPanel
|
|||||||
|
|
||||||
protected ImporterFrame _frame;
|
protected ImporterFrame _frame;
|
||||||
protected JButton _next;
|
protected JButton _next;
|
||||||
|
protected JPanel _spanel;
|
||||||
protected JTextArea _infoText;
|
protected JTextArea _infoText;
|
||||||
protected CDInfoEditor _infoEditor;
|
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;
|
package robodj.importer;
|
||||||
|
|
||||||
@@ -26,10 +26,11 @@ public class CDInfoEditor
|
|||||||
JLabel selLabel = new JLabel("Select...");
|
JLabel selLabel = new JLabel("Select...");
|
||||||
|
|
||||||
// create a string array for our combo box
|
// 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++) {
|
for (int i = 0; i < details.length; i++) {
|
||||||
names[i] = details[i].title;
|
names[i] = details[i].title;
|
||||||
}
|
}
|
||||||
|
names[details.length] = "<blank>";
|
||||||
|
|
||||||
_selBox = new JComboBox(names);
|
_selBox = new JComboBox(names);
|
||||||
selPanel.add(selLabel, GroupLayout.FIXED);
|
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;
|
package robodj.importer;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import com.samskivert.util.Log;
|
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
|
* The importer is the GUI-based application for ripping, encoding and
|
||||||
@@ -11,10 +17,40 @@ import com.samskivert.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class Importer
|
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 Log log = new Log("importer");
|
||||||
|
|
||||||
|
public static Properties config;
|
||||||
|
|
||||||
|
public static Repository repository;
|
||||||
|
|
||||||
public static void main (String[] args)
|
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();
|
ImporterFrame frame = new ImporterFrame();
|
||||||
InsertCDPanel panel = new InsertCDPanel();
|
InsertCDPanel panel = new InsertCDPanel();
|
||||||
frame.setPanel(panel);
|
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;
|
package robodj.importer;
|
||||||
|
|
||||||
@@ -24,7 +24,9 @@ public class ImporterFrame extends JFrame
|
|||||||
_top.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
_top.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
|
||||||
|
|
||||||
// create a container for our control buttons
|
// 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
|
// stick it into the frame
|
||||||
_top.add(_buttonPanel, GroupLayout.FIXED);
|
_top.add(_buttonPanel, GroupLayout.FIXED);
|
||||||
@@ -51,7 +53,6 @@ public class ImporterFrame extends JFrame
|
|||||||
// then stick the new panel in there
|
// then stick the new panel in there
|
||||||
if (panel != null) {
|
if (panel != null) {
|
||||||
_panel = panel;
|
_panel = panel;
|
||||||
_panel.setBackground(Color.yellow);
|
|
||||||
_top.add(_panel, 0);
|
_top.add(_panel, 0);
|
||||||
// let the panel know that it was added
|
// let the panel know that it was added
|
||||||
_panel.wasAddedToFrame(this);
|
_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;
|
package robodj.importer;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
public class Panel extends 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;
|
package robodj.importer;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ import com.samskivert.swing.util.*;
|
|||||||
import com.samskivert.swing.*;
|
import com.samskivert.swing.*;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import robodj.Log;
|
||||||
import robodj.convert.*;
|
import robodj.convert.*;
|
||||||
import robodj.repository.*;
|
import robodj.repository.*;
|
||||||
|
|
||||||
@@ -30,39 +32,324 @@ public class RipPanel
|
|||||||
setLayout(gl);
|
setLayout(gl);
|
||||||
|
|
||||||
// create our label for the left hand side
|
// 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));
|
cdlabel.setFont(new Font("Helvetica", Font.BOLD, 24));
|
||||||
add(cdlabel, GroupLayout.FIXED);
|
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
|
// save this stuff for later
|
||||||
_info = info;
|
_info = info;
|
||||||
_entry = entry;
|
_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)
|
public void wasAddedToFrame (ImporterFrame frame)
|
||||||
{
|
{
|
||||||
// keep this for later
|
// keep this for later
|
||||||
_frame = frame;
|
_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 = frame.addControlButton("Next...", "next", this);
|
||||||
_next.setEnabled(false);
|
_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)
|
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)
|
public void taskFailed (String name, Throwable exception)
|
||||||
{
|
{
|
||||||
if (name.equals("getinfo")) {
|
String msg;
|
||||||
|
if (Exception.class.equals(exception.getClass())) {
|
||||||
} else if (name.equals("cddb_lookup")) {
|
msg = exception.getMessage();
|
||||||
}
|
} else {
|
||||||
|
msg = exception.toString();
|
||||||
|
}
|
||||||
|
_statusLog.append("Error: " + msg + "\n");
|
||||||
|
Log.logStackTrace(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void actionPerformed (ActionEvent e)
|
public void actionPerformed (ActionEvent e)
|
||||||
@@ -72,6 +359,7 @@ public class RipPanel
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
|
|
||||||
} else if (cmd.equals("next")) {
|
} else if (cmd.equals("next")) {
|
||||||
|
System.exit(0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Unknown action event: " + cmd);
|
System.out.println("Unknown action event: " + cmd);
|
||||||
@@ -80,6 +368,12 @@ public class RipPanel
|
|||||||
|
|
||||||
protected ImporterFrame _frame;
|
protected ImporterFrame _frame;
|
||||||
protected JButton _next;
|
protected JButton _next;
|
||||||
|
protected JButton _cancel;
|
||||||
|
protected JLabel _actionLabel;
|
||||||
|
|
||||||
|
protected JProgressBar _oprogress;
|
||||||
|
protected JProgressBar _progress;
|
||||||
|
protected JTextArea _statusLog;
|
||||||
|
|
||||||
protected Ripper.TrackInfo[] _info;
|
protected Ripper.TrackInfo[] _info;
|
||||||
protected Entry _entry;
|
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;
|
package robodj.repository;
|
||||||
|
|
||||||
@@ -91,39 +91,30 @@ public class Repository extends MySQLRepository
|
|||||||
* and the song objects) will be filled in with the entryid of the
|
* and the song objects) will be filled in with the entryid of the
|
||||||
* newly created entry.
|
* newly created entry.
|
||||||
*/
|
*/
|
||||||
public void insertEntry (Entry entry)
|
public void insertEntry (final Entry entry)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
execute(new Operation () {
|
||||||
// insert the entry into the entry table
|
public void invoke () throws SQLException
|
||||||
_etable.insert(entry);
|
{
|
||||||
|
// insert the entry into the entry table
|
||||||
|
_etable.insert(entry);
|
||||||
|
|
||||||
// update the entryid now that it's known
|
// update the entryid now that it's known
|
||||||
entry.entryid = lastInsertedId();
|
entry.entryid = lastInsertedId();
|
||||||
|
|
||||||
// and insert all of it's songs into the songs table
|
// and insert all of it's songs into the songs table
|
||||||
if (entry.songs != null) {
|
if (entry.songs != null) {
|
||||||
for (int i = 0; i < entry.songs.length; i++) {
|
for (int i = 0; i < entry.songs.length; i++) {
|
||||||
// insert the proper entryid
|
// insert the proper entryid
|
||||||
entry.songs[i].entryid = entry.entryid;
|
entry.songs[i].entryid = entry.entryid;
|
||||||
_stable.insert(entry.songs[i]);
|
_stable.insert(entry.songs[i]);
|
||||||
// find out what songid was assigned
|
// find out what songid was assigned
|
||||||
entry.songs[i].songid = lastInsertedId();
|
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,57 +127,40 @@ public class Repository extends MySQLRepository
|
|||||||
* @see addSongToEntry
|
* @see addSongToEntry
|
||||||
* @see removeSongFromEntry
|
* @see removeSongFromEntry
|
||||||
*/
|
*/
|
||||||
public void updateEntry (Entry entry)
|
public void updateEntry (final Entry entry)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
execute(new Operation () {
|
||||||
// update the entry
|
public void invoke () throws SQLException
|
||||||
_etable.update(entry);
|
{
|
||||||
|
// update the entry
|
||||||
|
_etable.update(entry);
|
||||||
|
|
||||||
// and the entry's songs
|
// and the entry's songs
|
||||||
if (entry.songs != null) {
|
if (entry.songs != null) {
|
||||||
for (int i = 0; i < entry.songs.length; i++) {
|
for (int i = 0; i < entry.songs.length; i++) {
|
||||||
_stable.update(entry.songs[i]);
|
_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.
|
* Removes the entry (and all associated songs) from the database.
|
||||||
*/
|
*/
|
||||||
public void deleteEntry (Entry entry)
|
public void deleteEntry (final Entry entry)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
execute(new Operation () {
|
||||||
// remove the entry from the entry table and the foreign key
|
public void invoke () throws SQLException
|
||||||
// constraints will automatically remove all of the
|
{
|
||||||
// corresponding songs
|
// remove the entry from the entry table and the foreign
|
||||||
_etable.delete(entry);
|
// key constraints will automatically remove all of the
|
||||||
_session.commit();
|
// corresponding songs
|
||||||
|
_etable.delete(entry);
|
||||||
} 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,81 +175,55 @@ public class Repository extends MySQLRepository
|
|||||||
*
|
*
|
||||||
* @see updateSong
|
* @see updateSong
|
||||||
*/
|
*/
|
||||||
public void addSongToEntry (Entry entry, Song song)
|
public void addSongToEntry (final Entry entry, final Song song)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
execute(new Operation () {
|
||||||
// fill in the appropriate entry id value
|
public void invoke () throws SQLException
|
||||||
song.entryid = entry.entryid;
|
{
|
||||||
|
// fill in the appropriate entry id value
|
||||||
|
song.entryid = entry.entryid;
|
||||||
|
|
||||||
// and stick the song into the database
|
// and stick the song into the database
|
||||||
_stable.insert(song);
|
_stable.insert(song);
|
||||||
// communicate the songid back to the caller
|
// communicate the songid back to the caller
|
||||||
song.songid = lastInsertedId();
|
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
|
* Updates the specified song individually. The songid and entryid
|
||||||
* parameters should already be set to the appropriate values.
|
* parameters should already be set to the appropriate values.
|
||||||
*/
|
*/
|
||||||
public void updateSong (Song song)
|
public void updateSong (final Song song)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
execute(new Operation () {
|
||||||
_stable.update(song);
|
public void invoke () throws SQLException
|
||||||
_session.commit();
|
{
|
||||||
|
_stable.update(song);
|
||||||
} 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
|
* Creates a category with the specified name and returns the id of
|
||||||
* that new category.
|
* that new category.
|
||||||
*/
|
*/
|
||||||
public int createCategory (String name)
|
public int createCategory (final String name)
|
||||||
throws SQLException
|
throws SQLException
|
||||||
{
|
{
|
||||||
try {
|
execute(new Operation () {
|
||||||
Category cat = new Category();
|
public void invoke () throws SQLException
|
||||||
cat.name = name;
|
{
|
||||||
_ctable.insert(cat);
|
Category cat = new Category();
|
||||||
|
cat.name = name;
|
||||||
|
_ctable.insert(cat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
int categoryid = lastInsertedId();
|
return 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user