1 package camidion.chordhelper.midieditor;
2 import java.awt.Dimension;
3 import java.awt.event.ActionEvent;
4 import java.io.ByteArrayInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.util.Base64;
8 import java.util.regex.Pattern;
10 import javax.sound.midi.InvalidMidiDataException;
11 import javax.sound.midi.MidiSystem;
12 import javax.swing.AbstractAction;
13 import javax.swing.Action;
14 import javax.swing.Box;
15 import javax.swing.BoxLayout;
16 import javax.swing.JButton;
17 import javax.swing.JDialog;
18 import javax.swing.JOptionPane;
19 import javax.swing.JPanel;
20 import javax.swing.JScrollPane;
21 import javax.swing.JTextArea;
22 import javax.swing.event.DocumentEvent;
23 import javax.swing.event.DocumentListener;
25 import camidion.chordhelper.ButtonIcon;
26 import camidion.chordhelper.ChordHelperApplet;
31 public class Base64Dialog extends JDialog implements DocumentListener {
32 public static final Pattern HEADER_PATTERN = Pattern.compile("^.*:.*$", Pattern.MULTILINE);
33 private JTextArea base64TextArea = new JTextArea(8,56);
34 private void error(String message) {
35 JOptionPane.showMessageDialog(base64TextArea, (Object)message,
36 ChordHelperApplet.VersionInfo.NAME, JOptionPane.WARNING_MESSAGE);
37 base64TextArea.requestFocusInWindow();
39 private String createHeader(String filename) {
40 return "Content-Type: audio/midi; name=\"" + filename + "\"\n"
41 + "Content-Transfer-Encoding: base64\n\n";
43 public PlaylistTable playlistTable;
45 * 入力されたBase64テキストをデコードし、MIDIシーケンスとしてプレイリストに追加します。
46 * @return プレイリストに追加されたMIDIシーケンスのインデックス(先頭が0)、追加に失敗した場合は -1
48 public int addToPlaylist() {
49 byte[] midiData = null;
51 midiData = getMIDIData();
52 } catch(Exception e) {
53 error("Base64デコードに失敗しました。\n"+e);
56 try (InputStream in = new ByteArrayInputStream(midiData)) {
57 int index = playlistTable.getModel().add(MidiSystem.getSequence(in), null);
58 playlistTable.getSelectionModel().setSelectionInterval(index, index);
60 } catch( IOException|InvalidMidiDataException e ) {
61 error("Base64デコードした結果をMIDIシーケンスとして読み込めませんでした。\n"+e);
68 public Action addBase64Action = new AbstractAction("Add to PlayList", new ButtonIcon(ButtonIcon.EJECT_ICON)) {
69 { putValue(Action.SHORT_DESCRIPTION, "Base64デコードして、プレイリストへ追加"); }
71 public void actionPerformed(ActionEvent e) {
72 if( addToPlaylist() >= 0 ) setVisible(false);
78 public Action clearAction = new AbstractAction("Clear", new ButtonIcon(ButtonIcon.X_ICON)) {
79 { putValue(Action.SHORT_DESCRIPTION, "Base64テキスト欄を消去"); }
81 public void actionPerformed(ActionEvent e) { setText(null); }
84 * Base64テキスト入力ダイアログを構築します。
85 * @param playlistTable Base64デコードされたMIDIシーケンスの追加先プレイリストビュー
87 public Base64Dialog(PlaylistTable playlistTable) {
88 this.playlistTable = playlistTable;
89 setTitle("Base64-encoded MIDI sequence - " + ChordHelperApplet.VersionInfo.NAME);
91 setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
93 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
94 add(Box.createRigidArea(new Dimension(10, 0)));
95 add(new JButton(addBase64Action){{setMargin(ChordHelperApplet.ZERO_INSETS);}});
96 add(new JButton(clearAction){{setMargin(ChordHelperApplet.ZERO_INSETS);}});
98 add(new JScrollPane(base64TextArea));
100 setBounds( 300, 250, 660, 300 );
101 base64TextArea.setToolTipText("Paste Base64-encoded MIDI sequence here");
102 base64TextArea.getDocument().addDocumentListener(this);
103 addBase64Action.setEnabled(false);
104 clearAction.setEnabled(false);
107 public void insertUpdate(DocumentEvent e) {
108 addBase64Action.setEnabled(true);
109 clearAction.setEnabled(true);
112 public void removeUpdate(DocumentEvent e) {
113 if( e.getDocument().getLength() > 0 ) return;
114 addBase64Action.setEnabled(false);
115 clearAction.setEnabled(false);
118 public void changedUpdate(DocumentEvent e) { }
120 * バイナリー形式でMIDIデータを返します。
121 * @return バイナリー形式のMIDIデータ
122 * @throws IllegalArgumentException 入力されているテキストが有効なBase64スキームになっていない場合
124 public byte[] getMIDIData() {
125 String body = HEADER_PATTERN.matcher(base64TextArea.getText()).replaceAll("");
126 return Base64.getMimeDecoder().decode(body.getBytes());
129 * バイナリー形式のMIDIデータを設定します。
130 * @param midiData バイナリー形式のMIDIデータ
132 public void setMIDIData(byte[] midiData) { setMIDIData(midiData, null); }
134 * バイナリー形式のMIDIデータを、ファイル名をつけて設定します。
135 * @param midiData バイナリー形式のMIDIデータ
136 * @param filename ファイル名
138 public void setMIDIData(byte[] midiData, String filename) {
139 if( midiData == null || midiData.length == 0 ) return;
140 if( filename == null ) filename = "";
141 setText(createHeader(filename) + Base64.getMimeEncoder().encodeToString(midiData) + "\n");
142 base64TextArea.selectAll();
145 * Base64形式でMIDIデータを返します。
146 * @return Base64形式のMIDIデータ
148 public String getBase64Data() { return base64TextArea.getText(); }
150 * Base64形式のMIDIデータを設定します。
151 * @param base64Data Base64形式のMIDIデータ
153 public void setBase64Data(String base64Data) {
155 base64TextArea.append(base64Data);
158 * Base64形式のMIDIデータを、ファイル名をつけて設定します。
159 * @param base64Data Base64形式のMIDIデータ
160 * @param filename ファイル名
162 public void setBase64Data(String base64Data, String filename) {
163 setText(createHeader(filename));
164 base64TextArea.append(base64Data);
168 * @param text テキスト文字列
170 public void setText(String text) { base64TextArea.setText(text); }