/* * @(#)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(); } }