Rev 873 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
628 | adamjking | 1 | /* |
2 | * @(#)SysexSendReceiveGUI.java beta8 2006/04/23 |
||
3 | * |
||
4 | * Copyright (C) 2008 Adam King (adamjking@optusnet.com.au) |
||
5 | * |
||
6 | * This application is free software; you can redistribute it and/or modify |
||
7 | * it under the terms of the GNU General Public License as published by |
||
8 | * the Free Software Foundation; either version 2 of the License, or |
||
9 | * (at your option) any later version. |
||
10 | * |
||
11 | * This application is distributed in the hope that it will be useful, |
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | * GNU General Public License for more details. |
||
15 | * |
||
16 | * You should have received a copy of the GNU General Public License |
||
17 | * along with this application; if not, write to the Free Software |
||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
19 | */ |
||
20 | |||
21 | package org.midibox.midi.gui; |
||
22 | |||
23 | import java.awt.BorderLayout; |
||
24 | import java.awt.Color; |
||
25 | import java.awt.Component; |
||
26 | import java.awt.Dimension; |
||
27 | import java.awt.GridBagConstraints; |
||
28 | import java.awt.GridBagLayout; |
||
29 | import java.awt.Insets; |
||
30 | import java.awt.event.ActionEvent; |
||
31 | import java.awt.event.ActionListener; |
||
32 | import java.awt.event.ItemEvent; |
||
33 | import java.awt.event.ItemListener; |
||
34 | import java.io.File; |
||
850 | adamjking | 35 | import java.util.Iterator; |
36 | import java.util.LinkedList; |
||
628 | adamjking | 37 | import java.util.Observable; |
38 | import java.util.Observer; |
||
845 | tk | 39 | import java.util.StringTokenizer; |
850 | adamjking | 40 | import java.util.Vector; |
628 | adamjking | 41 | |
42 | import javax.swing.BorderFactory; |
||
43 | import javax.swing.JButton; |
||
850 | adamjking | 44 | import javax.swing.JComponent; |
628 | adamjking | 45 | import javax.swing.JFileChooser; |
46 | import javax.swing.JLabel; |
||
850 | adamjking | 47 | import javax.swing.JMenuItem; |
48 | import javax.swing.JOptionPane; |
||
628 | adamjking | 49 | import javax.swing.JPanel; |
850 | adamjking | 50 | import javax.swing.JPopupMenu; |
628 | adamjking | 51 | import javax.swing.JScrollPane; |
52 | import javax.swing.JSpinner; |
||
53 | import javax.swing.JTextField; |
||
54 | import javax.swing.JTextPane; |
||
55 | import javax.swing.SpinnerNumberModel; |
||
56 | import javax.swing.event.ChangeEvent; |
||
57 | import javax.swing.event.ChangeListener; |
||
850 | adamjking | 58 | import javax.swing.event.PopupMenuEvent; |
59 | import javax.swing.event.PopupMenuListener; |
||
60 | import javax.swing.text.Segment; |
||
628 | adamjking | 61 | import javax.swing.text.Style; |
62 | import javax.swing.text.StyleConstants; |
||
63 | import javax.swing.text.StyleContext; |
||
64 | import javax.swing.text.StyledDocument; |
||
65 | |||
66 | import org.midibox.midi.MidiUtils; |
||
67 | import org.midibox.midi.SysexSendReceive; |
||
68 | import org.midibox.utils.gui.ImageLoader; |
||
69 | import org.midibox.utils.gui.SimpleFileChooserFilter; |
||
850 | adamjking | 70 | import org.midibox.utils.gui.SplitButton; |
628 | adamjking | 71 | |
72 | public class SysexSendReceiveGUI extends JPanel implements ActionListener, |
||
73 | ItemListener, ChangeListener, Observer { |
||
74 | |||
850 | adamjking | 75 | private JPopupMenu MRUPopupMenu; |
76 | |||
77 | private SplitButton openMRUButton; |
||
78 | |||
79 | private static int maxMRU = 10; |
||
80 | |||
800 | adamjking | 81 | private static String currentDirectory = ""; |
628 | adamjking | 82 | |
850 | adamjking | 83 | private static Vector MRU = new Vector(); |
84 | |||
628 | adamjking | 85 | private static JFileChooser fc = null; |
86 | |||
87 | private SysexSendReceive sysexSendReceive; |
||
88 | |||
89 | // GUI components |
||
90 | |||
846 | tk | 91 | private JButton sendBrowseButton; |
92 | private JTextField sendFileName; |
||
93 | private JButton sendStartButton; |
||
94 | private JButton sendStopButton; |
||
95 | private JButton sendClearButton; |
||
850 | adamjking | 96 | private JButton sendSaveButton; |
628 | adamjking | 97 | |
846 | tk | 98 | private JButton receiveStartButton; |
99 | private JButton receiveStopButton; |
||
100 | private JButton receiveClearButton; |
||
850 | adamjking | 101 | private JButton receiveSaveButton; |
628 | adamjking | 102 | |
103 | private JTextPane sysexSendTextArea; |
||
104 | |||
105 | private JTextPane sysexReceiveTextArea; |
||
106 | |||
845 | tk | 107 | private JSpinner sendDelayTimeSpinner; |
628 | adamjking | 108 | |
109 | public SysexSendReceiveGUI(SysexSendReceive sysexSendReceive) { |
||
850 | adamjking | 110 | |
628 | adamjking | 111 | super(new BorderLayout()); |
112 | |||
113 | this.sysexSendReceive = sysexSendReceive; |
||
850 | adamjking | 114 | |
628 | adamjking | 115 | sysexSendReceive.addObserver(this); |
116 | |||
850 | adamjking | 117 | sendBrowseButton = new JButton("SysEx File", ImageLoader |
800 | adamjking | 118 | .getImageIcon("open.png")); |
846 | tk | 119 | sendFileName = new JTextField(); |
120 | sendFileName.setEditable(false); |
||
121 | sendBrowseButton.setActionCommand("sendBrowse"); |
||
122 | sendBrowseButton.addActionListener(this); |
||
628 | adamjking | 123 | |
846 | tk | 124 | sendStartButton = new JButton("Start"); |
125 | sendStartButton.setActionCommand("sendStart"); |
||
126 | sendStartButton.addActionListener(this); |
||
127 | sendStartButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
||
128 | sendStopButton = new JButton("Stop"); |
||
129 | sendStopButton.addActionListener(this); |
||
130 | sendStopButton.setActionCommand("sendStop"); |
||
131 | sendStopButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
||
132 | sendClearButton = new JButton("Clear"); |
||
133 | sendClearButton.addActionListener(this); |
||
134 | sendClearButton.setActionCommand("sendClear"); |
||
135 | sendClearButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
||
628 | adamjking | 136 | |
850 | adamjking | 137 | sendSaveButton = new JButton("", ImageLoader.getImageIcon("save.png")); |
138 | sendSaveButton.setActionCommand("sendSave"); |
||
139 | sendSaveButton.addActionListener(this); |
||
628 | adamjking | 140 | |
846 | tk | 141 | receiveStartButton = new JButton("Start"); |
142 | receiveStartButton.setActionCommand("receiveStart"); |
||
143 | receiveStartButton.addActionListener(this); |
||
144 | receiveStartButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
||
145 | receiveStopButton = new JButton("Stop"); |
||
146 | receiveStopButton.addActionListener(this); |
||
147 | receiveStopButton.setActionCommand("receiveStop"); |
||
148 | receiveStopButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
||
149 | receiveClearButton = new JButton("Clear"); |
||
150 | receiveClearButton.addActionListener(this); |
||
151 | receiveClearButton.setActionCommand("receiveClear"); |
||
152 | receiveClearButton.setAlignmentX(Component.LEFT_ALIGNMENT); |
||
850 | adamjking | 153 | receiveSaveButton = new JButton("", ImageLoader |
154 | .getImageIcon("save.png")); |
||
155 | receiveSaveButton.setActionCommand("receiveSave"); |
||
156 | receiveSaveButton.addActionListener(this); |
||
628 | adamjking | 157 | |
850 | adamjking | 158 | JPanel sendFileButtonsPanel = new JPanel(new BorderLayout(2, 2)); |
846 | tk | 159 | |
850 | adamjking | 160 | MRUPopupMenu = new JPopupMenu(); |
161 | MRUPopupMenu.addPopupMenuListener(new PopupMenuListener() { |
||
846 | tk | 162 | |
850 | adamjking | 163 | public void popupMenuCanceled(PopupMenuEvent e) { |
164 | |||
165 | } |
||
166 | |||
167 | public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { |
||
168 | |||
169 | } |
||
170 | |||
171 | public void popupMenuWillBecomeVisible(PopupMenuEvent e) { |
||
172 | |||
173 | SysexSendReceiveGUI.this.buildMRUMenu(MRUPopupMenu); |
||
174 | |||
175 | } |
||
176 | }); |
||
177 | |||
178 | openMRUButton = new SplitButton(sendBrowseButton, MRUPopupMenu); |
||
179 | openMRUButton.setRollover(true); |
||
180 | |||
181 | sendFileButtonsPanel.add(openMRUButton, BorderLayout.WEST); |
||
846 | tk | 182 | sendFileButtonsPanel.add(sendFileName, BorderLayout.CENTER); |
850 | adamjking | 183 | sendFileButtonsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, |
184 | 5)); |
||
846 | tk | 185 | |
186 | JPanel sendControlButtonsPanel = new JPanel(new GridBagLayout()); |
||
628 | adamjking | 187 | GridBagConstraints gbc = new GridBagConstraints(); |
188 | gbc.gridx = 0; |
||
189 | gbc.gridy = 0; |
||
190 | gbc.gridwidth = 1; |
||
191 | gbc.gridheight = 1; |
||
851 | adamjking | 192 | gbc.fill = GridBagConstraints.NONE; |
871 | adamjking | 193 | |
628 | adamjking | 194 | gbc.insets = new Insets(5, 5, 5, 5); |
195 | |||
846 | tk | 196 | sendControlButtonsPanel.add(sendStartButton, gbc); |
628 | adamjking | 197 | gbc.gridx++; |
198 | |||
199 | gbc.insets = new Insets(5, 13, 5, 5); |
||
200 | |||
846 | tk | 201 | sendControlButtonsPanel.add(sendStopButton, gbc); |
628 | adamjking | 202 | gbc.gridx++; |
203 | |||
846 | tk | 204 | gbc.insets = new Insets(5, 13, 5, 5); |
205 | |||
206 | sendControlButtonsPanel.add(sendClearButton, gbc); |
||
207 | gbc.gridx++; |
||
208 | |||
850 | adamjking | 209 | sendControlButtonsPanel.add(sendSaveButton, gbc); |
210 | gbc.gridx++; |
||
211 | |||
628 | adamjking | 212 | gbc.insets = new Insets(2, 2, 2, 2); |
213 | |||
214 | gbc.weightx = 1.0; |
||
846 | tk | 215 | sendControlButtonsPanel.add(new JPanel(), gbc); |
628 | adamjking | 216 | gbc.gridx++; |
217 | gbc.weightx = 0.0; |
||
218 | |||
219 | gbc.fill = GridBagConstraints.NONE; |
||
220 | |||
846 | tk | 221 | JLabel label = new JLabel("Delay between SysEx messages (ms): "); |
222 | sendControlButtonsPanel.add(label, gbc); |
||
628 | adamjking | 223 | gbc.gridx++; |
224 | |||
845 | tk | 225 | sendDelayTimeSpinner = new JSpinner(new SpinnerNumberModel( |
226 | sysexSendReceive.getSendDelayTime(), 1, 1000, 1)); |
||
227 | sendDelayTimeSpinner.addChangeListener(this); |
||
846 | tk | 228 | sendControlButtonsPanel.add(sendDelayTimeSpinner, gbc); |
628 | adamjking | 229 | |
846 | tk | 230 | JPanel receiveControlButtonsPanel = new JPanel(new GridBagLayout()); |
231 | gbc.gridx = 0; |
||
232 | gbc.gridy = 0; |
||
233 | gbc.gridwidth = 1; |
||
234 | gbc.gridheight = 1; |
||
235 | |||
236 | gbc.insets = new Insets(5, 5, 5, 5); |
||
237 | |||
238 | receiveControlButtonsPanel.add(receiveStartButton, gbc); |
||
239 | gbc.gridx++; |
||
240 | gbc.insets = new Insets(5, 13, 5, 5); |
||
241 | receiveControlButtonsPanel.add(receiveStopButton, gbc); |
||
242 | gbc.gridx++; |
||
243 | receiveControlButtonsPanel.add(receiveClearButton, gbc); |
||
850 | adamjking | 244 | gbc.gridx++; |
245 | receiveControlButtonsPanel.add(receiveSaveButton, gbc); |
||
846 | tk | 246 | |
628 | adamjking | 247 | JPanel sendPanel = new JPanel(new GridBagLayout()); |
248 | |||
249 | gbc.fill = GridBagConstraints.BOTH; |
||
250 | gbc.weightx = 1.0; |
||
251 | |||
252 | sendPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory |
||
253 | .createEmptyBorder(2, 2, 2, 2), BorderFactory |
||
254 | .createTitledBorder("Send"))); |
||
255 | |||
256 | sysexSendTextArea = new JTextPane(); |
||
257 | sysexSendTextArea.setBackground(Color.WHITE); |
||
845 | tk | 258 | sysexSendTextArea.setEditable(true); |
628 | adamjking | 259 | |
260 | StyledDocument doc = sysexSendTextArea.getStyledDocument(); |
||
261 | |||
262 | Style def = StyleContext.getDefaultStyleContext().getStyle( |
||
263 | StyleContext.DEFAULT_STYLE); |
||
264 | |||
265 | doc.addStyle("regular", def); |
||
266 | StyleConstants.setFontFamily(def, "Monospaced"); |
||
267 | |||
850 | adamjking | 268 | sysexSendTextArea.setLogicalStyle(def); |
269 | |||
270 | if (sysexSendReceive.getSendFile() != null) { |
||
271 | |||
272 | loadSysexSendFile(); |
||
273 | } |
||
274 | |||
628 | adamjking | 275 | JScrollPane sysexSendTextAreaScrollPane = new JScrollPane( |
276 | sysexSendTextArea); |
||
277 | sysexSendTextAreaScrollPane |
||
278 | .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); |
||
279 | |||
280 | // Make preferred width smaller than the other panel's minimum width. |
||
281 | sysexSendTextAreaScrollPane.setPreferredSize(new Dimension(300, 100)); |
||
282 | |||
846 | tk | 283 | gbc.insets = new Insets(5, 5, 5, 5); |
284 | gbc.gridy = 0; |
||
285 | gbc.gridx = 0; |
||
851 | adamjking | 286 | gbc.weighty = 0.0; |
846 | tk | 287 | sendPanel.add(sendFileButtonsPanel, gbc); |
628 | adamjking | 288 | gbc.gridy++; |
851 | adamjking | 289 | gbc.weighty = 0.0; |
846 | tk | 290 | sendPanel.add(sendControlButtonsPanel, gbc); |
291 | gbc.gridy++; |
||
292 | gbc.weighty = 1.0; |
||
628 | adamjking | 293 | sendPanel.add(sysexSendTextAreaScrollPane, gbc); |
294 | |||
295 | JPanel receivePanel = new JPanel(new GridBagLayout()); |
||
296 | receivePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory |
||
297 | .createEmptyBorder(2, 2, 2, 2), BorderFactory |
||
298 | .createTitledBorder("Receive"))); |
||
299 | |||
300 | sysexReceiveTextArea = new JTextPane(); |
||
301 | sysexReceiveTextArea.setBackground(Color.WHITE); |
||
302 | |||
845 | tk | 303 | sysexReceiveTextArea.setEditable(true); |
850 | adamjking | 304 | |
305 | doc = sysexReceiveTextArea.getStyledDocument(); |
||
306 | |||
307 | def = StyleContext.getDefaultStyleContext().getStyle( |
||
308 | StyleContext.DEFAULT_STYLE); |
||
309 | |||
310 | doc.addStyle("regular", def); |
||
311 | StyleConstants.setFontFamily(def, "Monospaced"); |
||
312 | |||
313 | sysexReceiveTextArea.setLogicalStyle(def); |
||
314 | |||
628 | adamjking | 315 | JScrollPane sysexReceiveTextAreaScrollPane = new JScrollPane( |
316 | sysexReceiveTextArea); |
||
317 | sysexReceiveTextAreaScrollPane |
||
318 | .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); |
||
319 | |||
320 | // Make preferred width smaller than the other panel's minimum width. |
||
321 | sysexReceiveTextAreaScrollPane |
||
322 | .setPreferredSize(new Dimension(300, 100)); |
||
323 | |||
846 | tk | 324 | gbc.insets = new Insets(5, 5, 5, 5); |
628 | adamjking | 325 | gbc.gridy = 0; |
846 | tk | 326 | gbc.gridx = 0; |
851 | adamjking | 327 | gbc.weighty = 0.0; |
846 | tk | 328 | gbc.fill = GridBagConstraints.NONE; |
329 | gbc.anchor = GridBagConstraints.WEST; |
||
330 | receivePanel.add(receiveControlButtonsPanel, gbc); |
||
331 | gbc.anchor = GridBagConstraints.CENTER; |
||
332 | gbc.fill = GridBagConstraints.BOTH; |
||
333 | gbc.gridy++; |
||
334 | gbc.weighty = 1.0; |
||
628 | adamjking | 335 | receivePanel.add(sysexReceiveTextAreaScrollPane, gbc); |
336 | |||
337 | JPanel mainPanel = new JPanel(new GridBagLayout()); |
||
338 | |||
339 | gbc.gridx = 0; |
||
340 | gbc.gridy = 0; |
||
341 | gbc.insets = new Insets(4, 4, 4, 4); |
||
342 | |||
343 | gbc.weighty = 1.0; |
||
344 | mainPanel.add(sendPanel, gbc); |
||
345 | gbc.gridy++; |
||
346 | mainPanel.add(receivePanel, gbc); |
||
347 | |||
800 | adamjking | 348 | add(mainPanel, BorderLayout.CENTER); |
628 | adamjking | 349 | |
350 | UIUpdate(); |
||
351 | } |
||
352 | |||
353 | public void UIUpdate() { |
||
850 | adamjking | 354 | boolean bUploading = (!sysexSendReceive.isSendCancelled() && !sysexSendReceive |
355 | .isSendDone()); |
||
846 | tk | 356 | boolean bReceiving = !sysexSendReceive.isReceiveStopped(); |
628 | adamjking | 357 | |
846 | tk | 358 | sendBrowseButton.setEnabled(!bUploading); |
359 | sendStartButton.setEnabled(!bUploading); |
||
360 | sendStopButton.setEnabled(bUploading); |
||
361 | sendClearButton.setEnabled(!bUploading); |
||
845 | tk | 362 | sendDelayTimeSpinner.setEnabled(!bUploading); |
363 | sysexSendTextArea.setEnabled(!bUploading); |
||
846 | tk | 364 | |
850 | adamjking | 365 | receiveSaveButton.setEnabled(!bReceiving); |
846 | tk | 366 | receiveStartButton.setEnabled(!bReceiving); |
367 | receiveStopButton.setEnabled(bReceiving); |
||
850 | adamjking | 368 | // receiveClearButton.setEnabled(!bReceiving); // better to allow clear |
369 | // while receiving |
||
846 | tk | 370 | sysexReceiveTextArea.setEnabled(!bReceiving); |
628 | adamjking | 371 | } |
372 | |||
373 | public void actionPerformed(ActionEvent e) { |
||
846 | tk | 374 | if (e.getActionCommand() == "sendStart") { |
845 | tk | 375 | byte[] sysexData = new byte[sysexSendReceive.getSendBufferSize()]; |
376 | int sysexDataOffset = 0; |
||
628 | adamjking | 377 | |
845 | tk | 378 | StyledDocument doc = sysexSendTextArea.getStyledDocument(); |
379 | int len = doc.getLength(); |
||
380 | |||
850 | adamjking | 381 | if (len > 0) { |
845 | tk | 382 | int nleft = len; |
383 | Segment text = new Segment(); |
||
384 | int offs = 0; |
||
850 | adamjking | 385 | text.setPartialReturn(true); |
845 | tk | 386 | while (nleft > 0) { |
387 | try { |
||
388 | doc.getText(offs, nleft, text); |
||
389 | } catch (Exception ex) { |
||
850 | adamjking | 390 | JOptionPane.showMessageDialog(null, |
391 | "Error while parsing hex digits!", |
||
392 | "Syntax Error", JOptionPane.ERROR_MESSAGE); |
||
845 | tk | 393 | return; |
394 | } |
||
395 | |||
396 | StringTokenizer st = new StringTokenizer(text.toString()); |
||
397 | while (st.hasMoreTokens()) { |
||
398 | int value; |
||
399 | |||
850 | adamjking | 400 | try { |
401 | value = (int) java.lang.Integer.parseInt(st |
||
402 | .nextToken(), 16); |
||
403 | sysexData[sysexDataOffset++] = (byte) value; |
||
404 | } catch (Exception ex) { |
||
405 | JOptionPane.showMessageDialog(null, |
||
406 | "Found invalid hexadecimal digit!", |
||
407 | "Syntax Error", JOptionPane.ERROR_MESSAGE); |
||
845 | tk | 408 | return; |
409 | } |
||
410 | } |
||
411 | |||
412 | nleft -= text.count; |
||
413 | offs += text.count; |
||
414 | } |
||
415 | |||
850 | adamjking | 416 | if (sysexDataOffset > 0) { |
845 | tk | 417 | final byte[] finalSysexData = sysexData; |
418 | final int finalSysexDataOffset = sysexDataOffset; |
||
419 | |||
420 | Thread t = new Thread() { |
||
850 | adamjking | 421 | public void run() { |
422 | sysexSendReceive.startSend(finalSysexData, |
||
423 | finalSysexDataOffset); |
||
424 | } |
||
425 | }; |
||
426 | |||
874 | adamjking | 427 | // t.setDaemon(true); |
845 | tk | 428 | t.start(); |
429 | } |
||
430 | } |
||
431 | |||
846 | tk | 432 | } else if (e.getActionCommand() == "sendStop") { |
433 | sysexSendReceive.sendCancel(); |
||
628 | adamjking | 434 | |
846 | tk | 435 | } else if (e.getActionCommand() == "sendClear") { |
436 | sysexSendTextArea.setText(""); |
||
437 | |||
438 | } else if (e.getActionCommand() == "sendBrowse") { |
||
628 | adamjking | 439 | onOpenSysexFile(); |
846 | tk | 440 | |
441 | } else if (e.getActionCommand() == "receiveStart") { |
||
442 | sysexSendReceive.setReceiveStopped(false); |
||
443 | |||
444 | } else if (e.getActionCommand() == "receiveStop") { |
||
445 | sysexSendReceive.setReceiveStopped(true); |
||
446 | |||
447 | } else if (e.getActionCommand() == "receiveClear") { |
||
448 | sysexReceiveTextArea.setText(""); |
||
449 | |||
850 | adamjking | 450 | } else if (e.getActionCommand() == "receiveSave") { |
451 | onSaveSysexFile(sysexReceiveTextArea.getStyledDocument()); |
||
452 | |||
453 | } else if (e.getActionCommand() == "sendSave") { |
||
454 | onSaveSysexFile(sysexSendTextArea.getStyledDocument()); |
||
628 | adamjking | 455 | } |
845 | tk | 456 | |
457 | UIUpdate(); |
||
628 | adamjking | 458 | } |
459 | |||
460 | protected void onOpenSysexFile() { |
||
461 | |||
462 | if (fc == null) { |
||
463 | fc = new JFileChooser(currentDirectory); |
||
464 | fc.addChoosableFileFilter(new SimpleFileChooserFilter( |
||
846 | tk | 465 | "SysEx files (*.syx)", "syx", "SysEx File")); |
628 | adamjking | 466 | } |
467 | |||
468 | File noFile = new File(""); |
||
469 | File noFiles[] = { noFile }; |
||
470 | fc.setSelectedFile(noFile); |
||
471 | fc.setSelectedFiles(noFiles); |
||
472 | |||
473 | int nRetVal = fc.showOpenDialog(this); |
||
474 | |||
475 | if (nRetVal == JFileChooser.APPROVE_OPTION) { |
||
850 | adamjking | 476 | |
628 | adamjking | 477 | File file = fc.getSelectedFile(); |
850 | adamjking | 478 | |
479 | openSysexSendFile(file); |
||
480 | |||
628 | adamjking | 481 | currentDirectory = fc.getCurrentDirectory().toString(); |
482 | } |
||
483 | } |
||
484 | |||
850 | adamjking | 485 | protected void onSaveSysexFile(StyledDocument doc) { |
846 | tk | 486 | |
487 | if (fc == null) { |
||
488 | fc = new JFileChooser(currentDirectory); |
||
489 | fc.addChoosableFileFilter(new SimpleFileChooserFilter( |
||
490 | "SysEx files (*.syx)", "syx", "SysEx File")); |
||
491 | } |
||
492 | |||
493 | File noFile = new File(""); |
||
494 | File noFiles[] = { noFile }; |
||
495 | fc.setSelectedFile(noFile); |
||
496 | fc.setSelectedFiles(noFiles); |
||
497 | |||
498 | int nRetVal = fc.showSaveDialog(this); |
||
499 | |||
500 | if (nRetVal == JFileChooser.APPROVE_OPTION) { |
||
501 | File file = fc.getSelectedFile(); |
||
502 | sysexSendReceive.setReceiveFile(file); |
||
503 | currentDirectory = fc.getCurrentDirectory().toString(); |
||
504 | |||
850 | adamjking | 505 | int maxSysexDataLen = 200000; // TODO: find better method... linked |
871 | adamjking | 506 | // list? |
846 | tk | 507 | byte[] sysexData = new byte[maxSysexDataLen]; |
508 | int sysexDataOffset = 0; |
||
509 | |||
510 | int len = doc.getLength(); |
||
511 | |||
850 | adamjking | 512 | if (len > 0) { |
846 | tk | 513 | int nleft = len; |
514 | Segment text = new Segment(); |
||
515 | int offs = 0; |
||
516 | text.setPartialReturn(true); |
||
517 | while (nleft > 0) { |
||
518 | try { |
||
519 | doc.getText(offs, nleft, text); |
||
520 | } catch (Exception ex) { |
||
850 | adamjking | 521 | JOptionPane.showMessageDialog(null, |
522 | "Error while parsing hex digits!", |
||
523 | "Syntax Error", JOptionPane.ERROR_MESSAGE); |
||
846 | tk | 524 | return; |
525 | } |
||
526 | |||
527 | StringTokenizer st = new StringTokenizer(text.toString()); |
||
528 | while (st.hasMoreTokens()) { |
||
529 | int value; |
||
530 | |||
850 | adamjking | 531 | if (sysexDataOffset >= maxSysexDataLen) { |
532 | JOptionPane.showMessageDialog(null, |
||
533 | "Too many SysEx bytes!", "Parsing Error", |
||
534 | JOptionPane.ERROR_MESSAGE); |
||
846 | tk | 535 | return; |
536 | } |
||
537 | |||
850 | adamjking | 538 | try { |
539 | value = (int) java.lang.Integer.parseInt(st |
||
540 | .nextToken(), 16); |
||
541 | sysexData[sysexDataOffset++] = (byte) value; |
||
542 | } catch (Exception ex) { |
||
543 | JOptionPane.showMessageDialog(null, |
||
544 | "Found invalid hexadecimal digit!", |
||
545 | "Syntax Error", JOptionPane.ERROR_MESSAGE); |
||
846 | tk | 546 | return; |
547 | } |
||
548 | } |
||
549 | |||
550 | nleft -= text.count; |
||
551 | offs += text.count; |
||
552 | } |
||
553 | |||
850 | adamjking | 554 | if (sysexDataOffset > 0) { |
555 | if (!sysexSendReceive.writeSysexFile(file, sysexData, |
||
556 | sysexDataOffset)) { |
||
557 | JOptionPane.showMessageDialog(null, |
||
558 | "Error while writing file!", |
||
559 | "File Access Error", JOptionPane.ERROR_MESSAGE); |
||
846 | tk | 560 | return; |
561 | } |
||
562 | } |
||
563 | } |
||
564 | } |
||
565 | } |
||
566 | |||
628 | adamjking | 567 | public void itemStateChanged(ItemEvent e) { |
568 | UIUpdate(); |
||
569 | } |
||
570 | |||
571 | public void stateChanged(ChangeEvent e) { |
||
572 | |||
845 | tk | 573 | Object source = e.getSource(); |
574 | |||
575 | if (source == sendDelayTimeSpinner) { |
||
850 | adamjking | 576 | sysexSendReceive.setSendDelayTime(((Integer) sendDelayTimeSpinner |
577 | .getValue()).intValue()); |
||
845 | tk | 578 | } |
579 | |||
628 | adamjking | 580 | UIUpdate(); |
581 | } |
||
582 | |||
583 | public void update(Observable observable, Object object) { |
||
850 | adamjking | 584 | |
628 | adamjking | 585 | if (observable == sysexSendReceive) { |
850 | adamjking | 586 | |
587 | if (object == sysexSendReceive.WORKER) { |
||
588 | |||
589 | } else if (object == sysexSendReceive.SEND_SYSEX_FILE) { |
||
590 | |||
591 | loadSysexSendFile(); |
||
592 | |||
593 | } else if (object == sysexSendReceive.RECEIVE_SYSEX_FILE) { |
||
594 | |||
846 | tk | 595 | StyledDocument doc = sysexReceiveTextArea.getStyledDocument(); |
628 | adamjking | 596 | |
846 | tk | 597 | LinkedList l = sysexSendReceive.getReceivedBytes(); |
850 | adamjking | 598 | |
846 | tk | 599 | int i; |
850 | adamjking | 600 | |
601 | for (i = 0; i < l.size(); ++i) { |
||
602 | byte[] data = (byte[]) l.get(i); |
||
846 | tk | 603 | try { |
850 | adamjking | 604 | if (doc.getLength() > 0) |
605 | doc.insertString(doc.getLength(), "\n", doc |
||
606 | .getStyle("regular")); |
||
607 | doc.insertString(doc.getLength(), "F0 ", doc |
||
608 | .getStyle("regular")); |
||
609 | doc.insertString(doc.getLength(), MidiUtils |
||
610 | .getHexString(data), doc.getStyle("regular")); |
||
846 | tk | 611 | } catch (Exception e) { |
612 | } |
||
613 | } |
||
850 | adamjking | 614 | |
846 | tk | 615 | sysexSendReceive.clearReceivedBytes(); |
628 | adamjking | 616 | } |
845 | tk | 617 | |
618 | UIUpdate(); |
||
628 | adamjking | 619 | } |
620 | } |
||
621 | |||
850 | adamjking | 622 | private void buildMRUMenu(JComponent menu) { |
623 | |||
624 | menu.removeAll(); |
||
625 | |||
626 | Iterator it = MRU.iterator(); |
||
627 | |||
628 | while (it.hasNext()) { |
||
629 | |||
630 | final JMenuItem menuItem = new JMenuItem((String) it.next()); |
||
631 | |||
632 | menuItem.addActionListener(new ActionListener() { |
||
633 | |||
634 | public void actionPerformed(ActionEvent ae) { |
||
635 | |||
636 | File file = new File(menuItem.getText()); |
||
637 | |||
638 | openSysexSendFile(file); |
||
639 | } |
||
640 | }); |
||
641 | |||
642 | menu.add(menuItem, 0); |
||
643 | } |
||
644 | } |
||
645 | |||
646 | protected void openSysexSendFile(File file) { |
||
647 | |||
648 | if (file.exists()) { |
||
649 | |||
650 | sysexSendReceive.setSendFile(file); |
||
651 | |||
652 | saveMRU(file.getPath()); |
||
653 | |||
654 | } else { |
||
655 | JOptionPane.showMessageDialog(this, "Hex file no longer exists", |
||
656 | "File does not exist", JOptionPane.ERROR_MESSAGE); |
||
657 | } |
||
658 | } |
||
659 | |||
660 | public static void saveMRU(String file) { |
||
661 | |||
662 | MRU.remove(file); |
||
663 | |||
664 | MRU.add(file); |
||
665 | |||
666 | for (int i = MRU.size() - maxMRU; i > 0; i--) { |
||
667 | |||
668 | MRU.removeElementAt(i - 1); |
||
669 | } |
||
670 | } |
||
671 | |||
672 | public static Vector getMRU() { |
||
673 | return MRU; |
||
674 | } |
||
675 | |||
628 | adamjking | 676 | public SysexSendReceive getSysexSendReceive() { |
677 | return sysexSendReceive; |
||
678 | } |
||
800 | adamjking | 679 | |
680 | public static String getCurrentDirectory() { |
||
681 | return currentDirectory; |
||
682 | } |
||
683 | |||
684 | public static void setCurrentDirectory(String currentDirectory) { |
||
685 | SysexSendReceiveGUI.currentDirectory = currentDirectory; |
||
686 | } |
||
808 | adamjking | 687 | |
850 | adamjking | 688 | private void loadSysexSendFile() { |
689 | |||
690 | sendFileName.setText(sysexSendReceive.getSendFile().getPath()); |
||
691 | |||
692 | sysexSendTextArea.setText(""); |
||
693 | |||
694 | StyledDocument doc = sysexSendTextArea.getStyledDocument(); |
||
695 | |||
696 | try { |
||
697 | doc.insertString(0, MidiUtils.getHexString(sysexSendReceive |
||
698 | .getSysexFile().getData()), doc.getStyle("regular")); |
||
699 | } catch (Exception e) { |
||
700 | |||
701 | } |
||
702 | } |
||
628 | adamjking | 703 | } |