/*
* @(#)Burn.java
*
* This file is part of webCDwriter - Network CD/DVD Writing.
*
* Copyright (C) 1999-2006 Jörg P. M. Haeger
*
* webCDwriter is free software. See CDcreator.java for details.
*/
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.io.*;
import java.text.*;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
/**
* Abstract parent of the burn command classes.
*
* @version 20060425
* @author Jörg P. M. Haeger
*/
abstract public class Burn extends Command {
final static String
hintBlankingTOC = "blanking TOC",
hintCDdetected = "CD detected",
hintCDrecordStarted = "cdrecord started",
hintCDwasClosed = "CD was closed",
hintDVDFormatStarted = "dvd-format started",
hintFixating = "fixating",
hintGrowisofsStarted = "growisofs started",
hintImageReady = "image ready",
hintMakingImage = "making image",
hintPercentDone = "percentDone",
hintVerifying = "verifying",
hintWriterReserved = "writer reserved"
;
final int
INIT = 0,
WAITING_FOR_WRITER = 1,
MEDIUM_DETECTED = 2,
VERIFY = 3,
DONE = 4;
int mode = INIT;
protected JOptionPane optionPane = null, subPane = null;
protected BurnDialog burnDialog;
JPanel writersPanel;
JTable table = null;
int totalKB, oldFreeKB, newFreeKB;
boolean CDwasClosed = false;
final String backButton = i18n("MainWin.back");
final JButton offlineButton = new JButton(i18n("burnOffline"));
Object[] options = { i18n("details"), okButtonText };
String burnSessionResult;
boolean burnSessionResultOK;
private int waitingQueuePosition = 1000;
private Icon cancelIcon = null;
Burn() {
burnDialog = new BurnDialog(this);
writersPanel = new JPanel();
writersPanel.setLayout(
new BoxLayout(writersPanel, BoxLayout.Y_AXIS));
writersPanel.setAlignmentX(Box.LEFT_ALIGNMENT);
offlineButton.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
String[] options = { backButton, okButtonText };
int res = showOptionDialog(
i18n("willNowExit"),
i18n("burnOffline"),
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null, options, backButton);
if (res == 1) {
writeHint("setBurnOffline");
try {
CDcreator.outStream.close();
}
catch (IOException e2) {
}
offline = true;
closeDialog();
}
}
});
}
void cancelCommand() {
Version.debug("cancel", "cancelCommand()");
if (mode == DONE)
closeDialog();
else {
super.cancelCommand();
writeHint("cancel");
}
}
private JDialog createErrorDialog() {
JPanel vbox = new JPanel();
vbox.setLayout(new BoxLayout(vbox, BoxLayout.Y_AXIS));
if (burnSessionResult.indexOf("http://") >= 0)
vbox.add(MainWin.createViewer(lastResult));
else {
// vbox.add(new JLabel(burnSessionResult));
JComponent viewer = MainWin.createViewer(burnSessionResult);
viewer.setAlignmentX(JPanel.LEFT_ALIGNMENT);
viewer.setPreferredSize(new Dimension(440, 200));
vbox.add(viewer);
if (burnSessionResult.indexOf(
"power calibration area error") >= 0) {
JComponent viewer2 = CDcreator.getHTML("errors/037303.html");
if (viewer2 != null && !CDcreator.isNetscapeVM()) {
viewer.setPreferredSize(new Dimension(440, 50));
vbox.add(Box.createVerticalStrut(10));
JScrollPane scroller = new JScrollPane();
scroller.setPreferredSize(new Dimension(440, 200));
scroller.setAlignmentX(Box.LEFT_ALIGNMENT);
scroller.getViewport().add(viewer2);
vbox.add(scroller);
}
}
}
optionPane = new JOptionPane(
vbox,
JOptionPane.ERROR_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null, options);
return optionPane.createDialog(
CDcreator.mainWin, i18n("error"));
}
protected JDialog createSuccessDialog() {
MessageFormat formatter = new MessageFormat("");
formatter.setLocale(CDcreator.locale);
if (CDwasClosed)
formatter.applyPattern(
i18n("burnSuccessCDwasClosed"));
else
formatter.applyPattern(i18n("burnSuccess"));
int writtenKB = oldFreeKB - newFreeKB;
if (totalKB < 1024 * 1024) {
// is a CD-R(W)
writtenKB -= 2 * (4500 + 2250);
if (oldFreeKB == totalKB)
// lead out of the first session
writtenKB -= 2 * 4500;
if (writtenKB < 0)
writtenKB = 0;
}
Object[] args = {
new Integer(writtenKB / 1024),
new Integer(newFreeKB / 1024),
new Integer(totalKB / 1024) };
optionPane = new JOptionPane(
formatter.format(args),
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null, options);
return optionPane.createDialog(
CDcreator.mainWin, i18n("titleBurnResult"));
}
private JTable createWriterTable() {
if (cancelIcon == null)
cancelIcon = MainWin.getIcon("delete_obj.gif");
JTable table = new JTable(ListWriters.tableModel);
table.setAlignmentX(JPanel.LEFT_ALIGNMENT);
// table.setPreferredScrollableViewportSize(new Dimension(400, 100));
javax.swing.table.TableColumnModel cols = table.getColumnModel();
cols.getColumn(0).setMaxWidth(30);
cols.getColumn(3).setMaxWidth(100);
cols.getColumn(4).setMaxWidth(24);
TableColumn col = cols.getColumn(3);
col.setCellRenderer(new TableCellRenderer() {
public java.awt.Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (!(value instanceof Integer))
return new JLabel("");
int n = ((Integer) value).intValue();
if (n < 0)
return new JLabel("");
JProgressBar bar = new JProgressBar();
bar.setStringPainted(true);
bar.setValue(n);
return bar;
}
});
col = table.getColumnModel().getColumn(4);
col.setCellRenderer(new TableCellRenderer() {
public java.awt.Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
if (value instanceof Boolean)
return new JButton(cancelIcon);
else
return new JLabel("");
}
});
col.setCellEditor(new DefaultCellEditor(new JCheckBox()) {
public java.awt.Component getTableCellEditorComponent(
final JTable table,
Object value,
boolean isSelected,
int row,
int column) {
final int no = row + 1;
final JButton button = new JButton(cancelIcon);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
writeHint("W" + no + " cancel");
// ListWriters.tableModel.setCancelButton(no, false);
button.setVisible(false);
}
});
if (value instanceof Boolean)
return button;
else
return new JLabel("");
}
});
table.setRowHeight(24);
table.setRowSelectionAllowed(false);
return table;
}
abstract protected void execBurnCommand();
protected void execOptions() {
}
protected void execSetProjectInfo() {
if (!CDcreator.askForProjectInfo)
return;
String from = Options.projectInfo.from;
if (from.length() == 0)
from = "-";
String to = Options.projectInfo.to;
if (to.length() == 0)
to = "-";
String label = Options.projectInfo.label;
if (label.length() == 0)
label = "-";
String contents = Options.projectInfo.contents;
if (contents.length() == 0)
contents = "-";
execCommand("setProjectInfo "
+ spaceToEsc(from) + " " + spaceToEsc(to)
+ " " + spaceToEsc(label) + " " + spaceToEsc(contents));
}
Dimension getPreferredSize() {
return new Dimension(540, 280);
}
protected void handleWindowEvent(WindowEvent e) {
Version.debug("show", "handleWindowEvent(" + e + ")");
if (table != null)
;
else
if (mode == WAITING_FOR_WRITER || mode == VERIFY)
cancelCommand();
else
if (mode == DONE)
closeDialog();
}
private void parseCapacityHint(String lineStr) {
Integer value = parse(lineStr, "capacity", 1);
if (value == null)
return;
totalKB = value.intValue();
value = parse(lineStr, "capacity", 2);
if (value == null)
return;
oldFreeKB = value.intValue();
value = parse(lineStr, "capacity", 3);
if (value == null)
return;
newFreeKB = value.intValue();
}
private void parseCDrecordLine(String lineStr) {
Integer value = parse(lineStr, "Track", 2);
if (value == null)
return;
int n = value.intValue();
value = parse(lineStr, "Track", 4);
if (value == null)
return;
int N = value.intValue();
setProgress(n, N);
if (oldFreeKB == 0)
oldFreeKB = 1024 * N;
}
private void parsePercentDoneHint(String line) {
int p = line.indexOf(".");
if (p > 0)
line = line.substring(0, p);
Integer value = parse(line, hintPercentDone, 1);
if (value == null)
return;
setProgress(value.intValue(), 100);
}
private void parseRankHint(String lineStr) {
Integer value = parse(lineStr, "rank", 1);
if (value == null)
return;
int rank = value.intValue();
if (rank < waitingQueuePosition)
waitingQueuePosition = rank;
else
rank = waitingQueuePosition;
JPanel vp = new JPanel();
vp.setLayout(new BoxLayout(vp, BoxLayout.Y_AXIS));
JPanel hp = new JPanel();
hp.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
hp.setLayout(new BoxLayout(hp, BoxLayout.X_AXIS));
hp.add(new JLabel(i18n("queue") + " " + rank));
hp.add(Box.createHorizontalStrut(10));
JButton button = new JButton(i18n("showStatus"));
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
CDcreator.showServerDocument("/status.html");
}
});
hp.add(button);
hp.setAlignmentX(Box.LEFT_ALIGNMENT);
vp.add(hp);
QueueView qv = new QueueView(rank);
qv.setAlignmentX(Box.LEFT_ALIGNMENT);
vp.add(qv);
vp.add(writersPanel);
optionPane.setMessage(vp);
validate();
}
protected void process(int code, String text) {
// System.out.println("code = " + code + ", text = " + text);
if (text.indexOf("eject") >= 0)
toLog(text);
String prefix = "";
if (writer >= 0)
prefix = "W" + writer + " ";
switch (code) {
case 101:
if (writer >= 0) {
ListWriters.tableModel.setState(
writer, i18n("BurnDialog.finished"));
ListWriters.tableModel.setCancelButton(writer, false);
setProgress(0, 0);
}
break;
case 199:
Version.debug("state", text);
String a = text.substring(0, 2);
java.awt.Component[] cs = writersPanel.getComponents();
int i = 0;
for (; i < cs.length; i++) {
JLabel l = (JLabel) cs[i];
String b = l.getText().substring(0, 2);
if (b.equals(a)) {
l.setText(text);
break;
}
}
if (i == cs.length)
writersPanel.add(new JLabel(text));
// activeDialog.pack();
break;
case 300:
ListWriters.tableModel.setState(writer, "");
ListWriters.tableModel.setCancelButton(writer, false);
break;
case 401:
ListWriters.tableModel.setState(writer, text);
ListWriters.tableModel.setCancelButton(writer, false);
setProgress(0, 0);
break;
case 601:
if (writer >= 0) {
ListWriters.tableModel.setState(writer, text);
setProgress(0, 0);
}
break;
case 900:
String str = i18n("MainWin.unexpectedNonEmptyCD");
if (showConfirmDialog(str,
i18n("warning"), JOptionPane.YES_NO_OPTION) == 0)
writeHint(prefix + "setAcceptNonEmptyCD");
break;
case 901:
if (text.indexOf("eject") >= 0)
break;
str = i18n("MainWin.unexpectedMedium");
str = CDcreator.replaceAll(str, "@MEDIUM@", text);
if (showConfirmDialog(str,
i18n("warning"), JOptionPane.YES_NO_OPTION) == 0)
writeHint(prefix + "setAcceptMedium");
break;
case 902:
str = i18n("MainWin.unexpectedEmptyCD");
if (showConfirmDialog(str,
i18n("warning"), JOptionPane.YES_NO_OPTION) == 0)
writeHint(prefix + "setAcceptEmptyCD");
break;
case 903:
// medium has user ID
break;
case 904:
str = i18n("MainWin.unexpectedWithoutUserID");
if (showConfirmDialog(str,
i18n("warning"), JOptionPane.YES_NO_OPTION) == 0)
writeHint(prefix + "setAcceptWithoutUserID");
break;
case 905:
String userID = "unknown";
int p0 = text.indexOf("\"");
if (p0 >= 0) {
int p1 = text.indexOf("\"", p0 + 1);
if (p1 > p0)
userID = text.substring(p0 + 1, p1);
}
str = i18n("MainWin.unexpectedUserID");
str = CDcreator.replaceAll(str, "@USER-ID@", userID);
if (showConfirmDialog(str,
i18n("warning"), JOptionPane.YES_NO_OPTION) == 0)
writeHint(prefix + "setAcceptKey2 " + userID);
break;
default:
;
}
}
void processHint(String str) {
// System.out.println("processHint " + str);
if (writer >= 0 && table == null)
table = createWriterTable();
if (str.startsWith("rank"))
parseRankHint(str);
else
if (str.startsWith("Track"))
parseCDrecordLine(str);
else
if (str.startsWith("capacity"))
parseCapacityHint(str);
else
if (str.startsWith(hintPercentDone))
parsePercentDoneHint(str);
else
if (str.equals(hintWriterReserved)) {
JPanel vbox = new JPanel();
vbox.setLayout(new BoxLayout(vbox, BoxLayout.Y_AXIS));
vbox.add(Box.createVerticalStrut(10));
JComponent viewer = MainWin.createViewer(infoStr);
viewer.setAlignmentX(JPanel.LEFT_ALIGNMENT);
JScrollPane scroller = new JScrollPane();
scroller.setAlignmentX(Box.LEFT_ALIGNMENT);
scroller.getViewport().add(viewer);
vbox.add(scroller);
vbox.add(Box.createVerticalStrut(5));
if (burnDialog == null || burnDialog.table == null) {
if (table != null) {
scroller = new JScrollPane(table);
scroller.setAlignmentX(JPanel.LEFT_ALIGNMENT);
vbox.add(scroller);
vbox.add(Box.createVerticalStrut(5));
}
Object[] options = { cancelButton, offlineButton };
optionPane = new JOptionPane(
vbox,
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION,
null, options);
show(optionPane, i18n("titleInsertCD"));
}
infoStr = "";
if (writer >= 0) {
ListWriters.tableModel.setCancelButton(writer, true);
ListWriters.tableModel.setState(writer, i18n("titleInsertCD"));
setProgress(0, 0);
}
}
else
if (str.equals(hintCDdetected)) {
mode = MEDIUM_DETECTED;
toLog("Medium detected");
if (writer < 0)
setProgress(0, 100);
else {
setProgress(0, 0);
ListWriters.tableModel.setCancelButton(writer, false);
burnDialog.setTable(table);
}
show(burnDialog, i18n("titleBurnSessionControl"));
}
else
if (str.equals(hintBlankingTOC)) {
toLog("");
toLog("cdrecord blank=fast started ==>");
setMessage(i18n("blankingTOC"));
setProgress(0, 100);
}
else
if (str.equals(hintDVDFormatStarted)) {
toLog("");
toLog("dvd+rw-format started ==>");
setMessage(i18n("BurnDialog.formatting"));
}
else
if (str.equals(hintMakingImage)) {
toLog("");
toLog("mkisofs started ==>");
setTitle(i18n("titleCreateImage"));
setMessage(i18n("createImage"));
setProgress(0, 100);
}
else
if (str.equals(hintCDrecordStarted)) {
toLog("");
toLog("cdrecord started ==>");
setTitle(i18n("titleBurn"));
setMessage(i18n("burn"));
setProgress(0, 100);
}
else
if (str.equals(hintGrowisofsStarted)) {
toLog("");
toLog("growisofs started ==>");
setTitle(i18n("titleBurn"));
setMessage(i18n("burn"));
setProgress(0, 100);
}
else
if (str.equals(hintFixating)) {
setMessage(i18n("fixating"));
setProgress(0, 100);
// burnDialog.setIndeterminate(true);
}
else
if (str.equals(hintCDwasClosed)) {
CDwasClosed = true;
}
else
if (str.equals(hintVerifying)) {
mode = VERIFY;
toLog("");
toLog("CDWverify started ==>");
setTitle(i18n("titleVerifying"));
setMessage(i18n("verifying"));
setProgress(0, 100);
if (writer < 0)
burnDialog.addButton(cancelButton);
else
ListWriters.tableModel.setCancelButton(writer, true);
}
else
if (str.equals("reload medium")) {
setMessage(i18n("BurnDialog.reload"));
burnDialog.setIndeterminate(true);
if (writer >= 0)
setProgress(0, 100);
}
else
if (str.equals("reload medium done")) {
setMessage(i18n("verifying"));
burnDialog.setIndeterminate(false);
setProgress(0, 100);
}
else
if (str.startsWith("Medium ")
|| str.indexOf("-> eject") >= 0) {
toLog(str);
final Object panel = optionPane.getMessage();
if (panel instanceof JPanel
&& Log.getView().getParent() != panel
&& Log.getView().getParent() != burnDialog) {
Log.getView().setPreferredSize(
new Dimension(160, 100));
Log.getView().setAlignmentX(
JPanel.LEFT_ALIGNMENT);
((JPanel)panel).add(Log.getView());
// activeDialog.pack();
/* Dimension d = activeDialog.getSize();
d.height += 100;
activeDialog.setSize(d);
CDcreator.view.center(activeDialog);
*/
optionPane.setMessage(panel);
optionPane.validate();
optionPane.repaint();
show(optionPane, i18n("titleInsertCD"));
}
}
}
void processInfo(String str) {
String masterCD = "Please insert the master CD into the drive No.";
if (str.indexOf(masterCD) >= 0) {
str = CDcreator.replaceAll(str,
masterCD, i18n("Burn.insertMaster"));
str += "
\n";
}
super.processInfo(str);
}
void processLog(String str) {
if (str.startsWith("Track ")) {
int p0 = str.indexOf("[buf ");
if (p0 > 0) {
int p1 = str.indexOf("%]", p0);
if (p1 > p0) {
p0 += 4;
while (str.charAt(p0) == ' ')
p0++;
String str2 = str.substring(p0, p1);
try {
int n = Integer.parseInt(str2);
burnDialog.setBuffer(n);
}
catch (Exception e) {
}
}
}
}
}
public void run() {
Object[] options = { cancelButton, offlineButton };
optionPane = new JOptionPane(
i18n("reserve"),
JOptionPane.INFORMATION_MESSAGE,
JOptionPane.DEFAULT_OPTION,
MainWin.getIcon("burn.png"), options, options[1]);
showCentered(optionPane, i18n("titleReserve"));
execCommand("resetOptions");
execOptions();
if (Options.format)
execCommand("setFormat");
if (Options.speed > 0)
execCommand("setSpeed " + Options.speed);
mode = WAITING_FOR_WRITER;
execBurnCommand();
if (cancel && mode == VERIFY)
cancel = false;
mode = DONE;
burnSessionResult = lastResult;
burnSessionResultOK = lastResultOK();
super.run();
}
protected void setMessage(String msg) {
if (writer < 0)
burnDialog.setMessage(msg);
else
ListWriters.tableModel.setState(writer, msg);
}
protected void setProgress(int current, int limit) {
burnDialog.setRange(0, limit);
burnDialog.setProgress(current);
if (writer >= 0) {
ListWriters.tableModel.setRange(writer, limit);
ListWriters.tableModel.setProgress(writer, current);
}
}
void showResult() {
if (table != null && !cancel) {
invokeLater(new Runnable() {
public void run() {
burnDialog.addButton(okButton);
}
});
return;
}
if (cancel || table != null) {
execSemaphore.setDone();
return;
}
// repair MainWin
CDcreator.restoreMainContentPane();
JDialog dialog;
if (burnSessionResultOK)
dialog = createSuccessDialog();
else
dialog = createErrorDialog();
while (true) {
optionPane.setInitialValue(options[1]);
optionPane.setValue(
JOptionPane.UNINITIALIZED_VALUE);
dialog.show();
if (optionPane.getValue() == options[0])
new LogWin().show();
else
break;
}
execSemaphore.setDone();
}
}