32,40 → 32,56 |
import java.awt.event.ItemEvent; |
import java.awt.event.ItemListener; |
import java.io.File; |
import java.util.Iterator; |
import java.util.LinkedList; |
import java.util.Observable; |
import java.util.Observer; |
import java.util.StringTokenizer; |
import java.util.LinkedList; |
import java.util.Vector; |
|
import javax.swing.BorderFactory; |
import javax.swing.JButton; |
import javax.swing.JComponent; |
import javax.swing.JFileChooser; |
import javax.swing.JLabel; |
import javax.swing.JMenuItem; |
import javax.swing.JOptionPane; |
import javax.swing.JPanel; |
import javax.swing.JPopupMenu; |
import javax.swing.JScrollPane; |
import javax.swing.JSpinner; |
import javax.swing.JTextField; |
import javax.swing.JTextPane; |
import javax.swing.JOptionPane; |
import javax.swing.SpinnerNumberModel; |
import javax.swing.event.ChangeEvent; |
import javax.swing.event.ChangeListener; |
import javax.swing.event.PopupMenuEvent; |
import javax.swing.event.PopupMenuListener; |
import javax.swing.text.Segment; |
import javax.swing.text.Style; |
import javax.swing.text.StyleConstants; |
import javax.swing.text.StyleContext; |
import javax.swing.text.StyledDocument; |
import javax.swing.text.Segment; |
|
import org.midibox.midi.MidiUtils; |
import org.midibox.midi.SysexSendReceive; |
import org.midibox.utils.gui.ImageLoader; |
import org.midibox.utils.gui.SimpleFileChooserFilter; |
import org.midibox.utils.gui.SplitButton; |
|
public class SysexSendReceiveGUI extends JPanel implements ActionListener, |
ItemListener, ChangeListener, Observer { |
|
private JPopupMenu MRUPopupMenu; |
|
private SplitButton openMRUButton; |
|
private static int maxMRU = 10; |
|
private static String currentDirectory = ""; |
|
private static Vector MRU = new Vector(); |
|
private static JFileChooser fc = null; |
|
private SysexSendReceive sysexSendReceive; |
77,12 → 93,12 |
private JButton sendStartButton; |
private JButton sendStopButton; |
private JButton sendClearButton; |
private JButton sendSaveButton; |
|
private JButton receiveBrowseButton; |
private JTextField receiveFileName; |
private JButton receiveStartButton; |
private JButton receiveStopButton; |
private JButton receiveClearButton; |
private JButton receiveSaveButton; |
|
private JTextPane sysexSendTextArea; |
|
91,12 → 107,14 |
private JSpinner sendDelayTimeSpinner; |
|
public SysexSendReceiveGUI(SysexSendReceive sysexSendReceive) { |
|
super(new BorderLayout()); |
|
this.sysexSendReceive = sysexSendReceive; |
|
sysexSendReceive.addObserver(this); |
|
sendBrowseButton = new JButton("Open File", ImageLoader |
sendBrowseButton = new JButton("SysEx File", ImageLoader |
.getImageIcon("open.png")); |
sendFileName = new JTextField(); |
sendFileName.setEditable(false); |
116,14 → 134,10 |
sendClearButton.setActionCommand("sendClear"); |
sendClearButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
|
sendSaveButton = new JButton("", ImageLoader.getImageIcon("save.png")); |
sendSaveButton.setActionCommand("sendSave"); |
sendSaveButton.addActionListener(this); |
|
receiveBrowseButton = new JButton("Save File", ImageLoader |
.getImageIcon("open.png")); |
receiveFileName = new JTextField(); |
receiveFileName.setEditable(false); |
receiveBrowseButton.setActionCommand("receiveBrowse"); |
receiveBrowseButton.addActionListener(this); |
|
receiveStartButton = new JButton("Start"); |
receiveStartButton.setActionCommand("receiveStart"); |
receiveStartButton.addActionListener(this); |
136,13 → 150,38 |
receiveClearButton.addActionListener(this); |
receiveClearButton.setActionCommand("receiveClear"); |
receiveClearButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
receiveSaveButton = new JButton("", ImageLoader |
.getImageIcon("save.png")); |
receiveSaveButton.setActionCommand("receiveSave"); |
receiveSaveButton.addActionListener(this); |
|
JPanel sendFileButtonsPanel = new JPanel(new BorderLayout(2, 2)); |
|
MRUPopupMenu = new JPopupMenu(); |
MRUPopupMenu.addPopupMenuListener(new PopupMenuListener() { |
|
JPanel sendFileButtonsPanel = new JPanel(new BorderLayout(2, 2)); |
sendFileButtonsPanel.add(sendBrowseButton, BorderLayout.WEST); |
public void popupMenuCanceled(PopupMenuEvent e) { |
|
} |
|
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { |
|
} |
|
public void popupMenuWillBecomeVisible(PopupMenuEvent e) { |
|
SysexSendReceiveGUI.this.buildMRUMenu(MRUPopupMenu); |
|
} |
}); |
|
openMRUButton = new SplitButton(sendBrowseButton, MRUPopupMenu); |
openMRUButton.setRollover(true); |
|
sendFileButtonsPanel.add(openMRUButton, BorderLayout.WEST); |
sendFileButtonsPanel.add(sendFileName, BorderLayout.CENTER); |
sendFileButtonsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); |
sendFileButtonsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, |
5)); |
|
JPanel sendControlButtonsPanel = new JPanel(new GridBagLayout()); |
GridBagConstraints gbc = new GridBagConstraints(); |
166,6 → 205,9 |
sendControlButtonsPanel.add(sendClearButton, gbc); |
gbc.gridx++; |
|
sendControlButtonsPanel.add(sendSaveButton, gbc); |
gbc.gridx++; |
|
gbc.insets = new Insets(2, 2, 2, 2); |
|
gbc.weightx = 1.0; |
184,13 → 226,6 |
sendDelayTimeSpinner.addChangeListener(this); |
sendControlButtonsPanel.add(sendDelayTimeSpinner, gbc); |
|
|
|
JPanel receiveFileButtonsPanel = new JPanel(new BorderLayout(2, 2)); |
receiveFileButtonsPanel.add(receiveBrowseButton, BorderLayout.WEST); |
receiveFileButtonsPanel.add(receiveFileName, BorderLayout.CENTER); |
receiveFileButtonsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); |
|
JPanel receiveControlButtonsPanel = new JPanel(new GridBagLayout()); |
gbc.gridx = 0; |
gbc.gridy = 0; |
205,9 → 240,9 |
receiveControlButtonsPanel.add(receiveStopButton, gbc); |
gbc.gridx++; |
receiveControlButtonsPanel.add(receiveClearButton, gbc); |
gbc.gridx++; |
receiveControlButtonsPanel.add(receiveSaveButton, gbc); |
|
|
|
JPanel sendPanel = new JPanel(new GridBagLayout()); |
|
gbc.fill = GridBagConstraints.BOTH; |
229,6 → 264,13 |
doc.addStyle("regular", def); |
StyleConstants.setFontFamily(def, "Monospaced"); |
|
sysexSendTextArea.setLogicalStyle(def); |
|
if (sysexSendReceive.getSendFile() != null) { |
|
loadSysexSendFile(); |
} |
|
JScrollPane sysexSendTextAreaScrollPane = new JScrollPane( |
sysexSendTextArea); |
sysexSendTextAreaScrollPane |
248,7 → 290,6 |
gbc.weighty = 1.0; |
sendPanel.add(sysexSendTextAreaScrollPane, gbc); |
|
|
JPanel receivePanel = new JPanel(new GridBagLayout()); |
receivePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory |
.createEmptyBorder(2, 2, 2, 2), BorderFactory |
258,6 → 299,17 |
sysexReceiveTextArea.setBackground(Color.WHITE); |
|
sysexReceiveTextArea.setEditable(true); |
|
doc = sysexReceiveTextArea.getStyledDocument(); |
|
def = StyleContext.getDefaultStyleContext().getStyle( |
StyleContext.DEFAULT_STYLE); |
|
doc.addStyle("regular", def); |
StyleConstants.setFontFamily(def, "Monospaced"); |
|
sysexReceiveTextArea.setLogicalStyle(def); |
|
JScrollPane sysexReceiveTextAreaScrollPane = new JScrollPane( |
sysexReceiveTextArea); |
sysexReceiveTextAreaScrollPane |
271,10 → 323,6 |
gbc.gridy = 0; |
gbc.gridx = 0; |
gbc.weighty = 1.0; |
receivePanel.add(receiveFileButtonsPanel, gbc); |
gbc.gridx = 0; |
gbc.gridy++; |
gbc.weighty = 1.0; |
gbc.fill = GridBagConstraints.NONE; |
gbc.anchor = GridBagConstraints.WEST; |
receivePanel.add(receiveControlButtonsPanel, gbc); |
301,7 → 349,8 |
} |
|
public void UIUpdate() { |
boolean bUploading = (!sysexSendReceive.isSendCancelled() && !sysexSendReceive.isSendDone()); |
boolean bUploading = (!sysexSendReceive.isSendCancelled() && !sysexSendReceive |
.isSendDone()); |
boolean bReceiving = !sysexSendReceive.isReceiveStopped(); |
|
sendBrowseButton.setEnabled(!bUploading); |
311,14 → 360,14 |
sendDelayTimeSpinner.setEnabled(!bUploading); |
sysexSendTextArea.setEnabled(!bUploading); |
|
receiveBrowseButton.setEnabled(!bReceiving); |
receiveSaveButton.setEnabled(!bReceiving); |
receiveStartButton.setEnabled(!bReceiving); |
receiveStopButton.setEnabled(bReceiving); |
//receiveClearButton.setEnabled(!bReceiving); // better to allow clear while receiving |
// receiveClearButton.setEnabled(!bReceiving); // better to allow clear |
// while receiving |
sysexReceiveTextArea.setEnabled(!bReceiving); |
} |
|
|
public void actionPerformed(ActionEvent e) { |
if (e.getActionCommand() == "sendStart") { |
byte[] sysexData = new byte[sysexSendReceive.getSendBufferSize()]; |
327,16 → 376,18 |
StyledDocument doc = sysexSendTextArea.getStyledDocument(); |
int len = doc.getLength(); |
|
if( len > 0 ) { |
if (len > 0) { |
int nleft = len; |
Segment text = new Segment(); |
int offs = 0; |
text.setPartialReturn(true); |
text.setPartialReturn(true); |
while (nleft > 0) { |
try { |
doc.getText(offs, nleft, text); |
} catch (Exception ex) { |
JOptionPane.showMessageDialog(null, "Error while parsing hex digits!", "Syntax Error", JOptionPane.ERROR_MESSAGE); |
JOptionPane.showMessageDialog(null, |
"Error while parsing hex digits!", |
"Syntax Error", JOptionPane.ERROR_MESSAGE); |
return; |
} |
|
344,11 → 395,14 |
while (st.hasMoreTokens()) { |
int value; |
|
try { |
value = (int)java.lang.Integer.parseInt(st.nextToken(), 16); |
sysexData[sysexDataOffset++] = (byte)value; |
} catch(Exception ex) { |
JOptionPane.showMessageDialog(null, "Found invalid hexadecimal digit!", "Syntax Error", JOptionPane.ERROR_MESSAGE); |
try { |
value = (int) java.lang.Integer.parseInt(st |
.nextToken(), 16); |
sysexData[sysexDataOffset++] = (byte) value; |
} catch (Exception ex) { |
JOptionPane.showMessageDialog(null, |
"Found invalid hexadecimal digit!", |
"Syntax Error", JOptionPane.ERROR_MESSAGE); |
return; |
} |
} |
357,16 → 411,17 |
offs += text.count; |
} |
|
if( sysexDataOffset > 0 ) { |
if (sysexDataOffset > 0) { |
final byte[] finalSysexData = sysexData; |
final int finalSysexDataOffset = sysexDataOffset; |
|
Thread t = new Thread() { |
public void run() { |
sysexSendReceive.startSend(finalSysexData, finalSysexDataOffset); |
} |
}; |
|
public void run() { |
sysexSendReceive.startSend(finalSysexData, |
finalSysexDataOffset); |
} |
}; |
|
t.start(); |
} |
} |
389,8 → 444,11 |
} else if (e.getActionCommand() == "receiveClear") { |
sysexReceiveTextArea.setText(""); |
|
} else if (e.getActionCommand() == "receiveBrowse") { |
onSaveSysexFile(); |
} else if (e.getActionCommand() == "receiveSave") { |
onSaveSysexFile(sysexReceiveTextArea.getStyledDocument()); |
|
} else if (e.getActionCommand() == "sendSave") { |
onSaveSysexFile(sysexSendTextArea.getStyledDocument()); |
} |
|
UIUpdate(); |
412,13 → 470,16 |
int nRetVal = fc.showOpenDialog(this); |
|
if (nRetVal == JFileChooser.APPROVE_OPTION) { |
|
File file = fc.getSelectedFile(); |
sysexSendReceive.setSendFile(file); |
|
openSysexSendFile(file); |
|
currentDirectory = fc.getCurrentDirectory().toString(); |
} |
} |
|
protected void onSaveSysexFile() { |
protected void onSaveSysexFile(StyledDocument doc) { |
|
if (fc == null) { |
fc = new JFileChooser(currentDirectory); |
438,14 → 499,14 |
sysexSendReceive.setReceiveFile(file); |
currentDirectory = fc.getCurrentDirectory().toString(); |
|
int maxSysexDataLen = 200000; // TODO: find better method... linked list? |
int maxSysexDataLen = 200000; // TODO: find better method... linked |
// list? |
byte[] sysexData = new byte[maxSysexDataLen]; |
int sysexDataOffset = 0; |
|
StyledDocument doc = sysexReceiveTextArea.getStyledDocument(); |
int len = doc.getLength(); |
|
if( len > 0 ) { |
if (len > 0) { |
int nleft = len; |
Segment text = new Segment(); |
int offs = 0; |
454,7 → 515,9 |
try { |
doc.getText(offs, nleft, text); |
} catch (Exception ex) { |
JOptionPane.showMessageDialog(null, "Error while parsing hex digits!", "Syntax Error", JOptionPane.ERROR_MESSAGE); |
JOptionPane.showMessageDialog(null, |
"Error while parsing hex digits!", |
"Syntax Error", JOptionPane.ERROR_MESSAGE); |
return; |
} |
|
462,16 → 525,21 |
while (st.hasMoreTokens()) { |
int value; |
|
if( sysexDataOffset >= maxSysexDataLen ) { |
JOptionPane.showMessageDialog(null, "Too many SysEx bytes!", "Parsing Error", JOptionPane.ERROR_MESSAGE); |
if (sysexDataOffset >= maxSysexDataLen) { |
JOptionPane.showMessageDialog(null, |
"Too many SysEx bytes!", "Parsing Error", |
JOptionPane.ERROR_MESSAGE); |
return; |
} |
|
try { |
value = (int)java.lang.Integer.parseInt(st.nextToken(), 16); |
sysexData[sysexDataOffset++] = (byte)value; |
} catch(Exception ex) { |
JOptionPane.showMessageDialog(null, "Found invalid hexadecimal digit!", "Syntax Error", JOptionPane.ERROR_MESSAGE); |
try { |
value = (int) java.lang.Integer.parseInt(st |
.nextToken(), 16); |
sysexData[sysexDataOffset++] = (byte) value; |
} catch (Exception ex) { |
JOptionPane.showMessageDialog(null, |
"Found invalid hexadecimal digit!", |
"Syntax Error", JOptionPane.ERROR_MESSAGE); |
return; |
} |
} |
480,9 → 548,12 |
offs += text.count; |
} |
|
if( sysexDataOffset > 0 ) { |
if( !sysexSendReceive.writeSysexFile(file, sysexData, sysexDataOffset) ) { |
JOptionPane.showMessageDialog(null, "Error while writing file!", "File Access Error", JOptionPane.ERROR_MESSAGE); |
if (sysexDataOffset > 0) { |
if (!sysexSendReceive.writeSysexFile(file, sysexData, |
sysexDataOffset)) { |
JOptionPane.showMessageDialog(null, |
"Error while writing file!", |
"File Access Error", JOptionPane.ERROR_MESSAGE); |
return; |
} |
} |
499,7 → 570,8 |
Object source = e.getSource(); |
|
if (source == sendDelayTimeSpinner) { |
sysexSendReceive.setSendDelayTime(((Integer) sendDelayTimeSpinner.getValue()).intValue()); |
sysexSendReceive.setSendDelayTime(((Integer) sendDelayTimeSpinner |
.getValue()).intValue()); |
} |
|
UIUpdate(); |
506,39 → 578,38 |
} |
|
public void update(Observable observable, Object object) { |
|
if (observable == sysexSendReceive) { |
if (object == sysexSendReceive.WORKER ) { |
} else if (object == sysexSendReceive.getSendFile()) { |
sendFileName.setText(sysexSendReceive.getSendFile().getPath()); |
sysexSendTextArea.setText(""); |
StyledDocument doc = sysexSendTextArea.getStyledDocument(); |
try { |
doc |
.insertString(0, MidiUtils |
.getHexString(sysexSendReceive |
.getSysexFile().getData()), doc |
.getStyle("regular")); |
} catch (Exception e) { |
} |
} else if (object == sysexSendReceive.getReceivedBytes()) { |
|
if (object == sysexSendReceive.WORKER) { |
|
} else if (object == sysexSendReceive.SEND_SYSEX_FILE) { |
|
loadSysexSendFile(); |
|
} else if (object == sysexSendReceive.RECEIVE_SYSEX_FILE) { |
|
StyledDocument doc = sysexReceiveTextArea.getStyledDocument(); |
|
LinkedList l = sysexSendReceive.getReceivedBytes(); |
|
int i; |
for(i=0; i<l.size(); ++i) { |
byte[] data = (byte[])l.get(i); |
|
for (i = 0; i < l.size(); ++i) { |
byte[] data = (byte[]) l.get(i); |
try { |
if( doc.getLength() > 0 ) |
doc.insertString(doc.getLength(), "\n", doc.getStyle("regular")); |
doc.insertString(doc.getLength(), "F0 ", doc.getStyle("regular")); |
doc.insertString(doc.getLength(), MidiUtils.getHexString(data), doc.getStyle("regular")); |
if (doc.getLength() > 0) |
doc.insertString(doc.getLength(), "\n", doc |
.getStyle("regular")); |
doc.insertString(doc.getLength(), "F0 ", doc |
.getStyle("regular")); |
doc.insertString(doc.getLength(), MidiUtils |
.getHexString(data), doc.getStyle("regular")); |
} catch (Exception e) { |
} |
} |
|
sysexSendReceive.clearReceivedBytes(); |
|
} else if (object == sysexSendReceive.getReceiveFile()) { |
receiveFileName.setText(sysexSendReceive.getReceiveFile().getPath()); |
} |
|
UIUpdate(); |
545,6 → 616,60 |
} |
} |
|
private void buildMRUMenu(JComponent menu) { |
|
menu.removeAll(); |
|
Iterator it = MRU.iterator(); |
|
while (it.hasNext()) { |
|
final JMenuItem menuItem = new JMenuItem((String) it.next()); |
|
menuItem.addActionListener(new ActionListener() { |
|
public void actionPerformed(ActionEvent ae) { |
|
File file = new File(menuItem.getText()); |
|
openSysexSendFile(file); |
} |
}); |
|
menu.add(menuItem, 0); |
} |
} |
|
protected void openSysexSendFile(File file) { |
|
if (file.exists()) { |
|
sysexSendReceive.setSendFile(file); |
|
saveMRU(file.getPath()); |
|
} else { |
JOptionPane.showMessageDialog(this, "Hex file no longer exists", |
"File does not exist", JOptionPane.ERROR_MESSAGE); |
} |
} |
|
public static void saveMRU(String file) { |
|
MRU.remove(file); |
|
MRU.add(file); |
|
for (int i = MRU.size() - maxMRU; i > 0; i--) { |
|
MRU.removeElementAt(i - 1); |
} |
} |
|
public static Vector getMRU() { |
return MRU; |
} |
|
public SysexSendReceive getSysexSendReceive() { |
return sysexSendReceive; |
} |
557,4 → 682,19 |
SysexSendReceiveGUI.currentDirectory = currentDirectory; |
} |
|
private void loadSysexSendFile() { |
|
sendFileName.setText(sysexSendReceive.getSendFile().getPath()); |
|
sysexSendTextArea.setText(""); |
|
StyledDocument doc = sysexSendTextArea.getStyledDocument(); |
|
try { |
doc.insertString(0, MidiUtils.getHexString(sysexSendReceive |
.getSysexFile().getData()), doc.getStyle("regular")); |
} catch (Exception e) { |
|
} |
} |
} |