OSDN Git Service

・Base64エディタが空のときにボタンを押せないようにした
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sun, 6 Nov 2016 14:34:43 +0000 (23:34 +0900)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sun, 6 Nov 2016 14:34:43 +0000 (23:34 +0900)
・リファクタリング

src/camidion/chordhelper/ChordHelperApplet.java
src/camidion/chordhelper/chorddiagram/CapoComboBoxModel.java
src/camidion/chordhelper/chorddiagram/CapoSelecterView.java
src/camidion/chordhelper/chorddiagram/ChordDiagram.java
src/camidion/chordhelper/mididevice/AbstractVirtualMidiDevice.java
src/camidion/chordhelper/mididevice/MidiDeviceInOutType.java
src/camidion/chordhelper/mididevice/MidiDeviceModel.java
src/camidion/chordhelper/mididevice/MidiDeviceTreeModel.java
src/camidion/chordhelper/mididevice/MidiDeviceTreeView.java
src/camidion/chordhelper/mididevice/MidiSequencerModel.java
src/camidion/chordhelper/midieditor/Base64Dialog.java

index f95688f..233a63f 100644 (file)
@@ -283,7 +283,7 @@ public class ChordHelperApplet extends JApplet {
         */
        public static class VersionInfo {
                public static final String      NAME = "MIDI Chord Helper";
-               public static final String      VERSION = "Ver.20161010.1";
+               public static final String      VERSION = "Ver.20161106.1";
                public static final String      COPYRIGHT = "Copyright (C) 2004-2016";
                public static final String      AUTHER = "@きよし - Akiyoshi Kamide";
                public static final String      URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
index cfb0aef..baf596c 100644 (file)
@@ -7,11 +7,11 @@ import javax.swing.event.ListDataListener;
  * カポ選択コンボボックスモデル(選択範囲:1~11)
  */
 public class CapoComboBoxModel implements ComboBoxModel<Integer> {
-       private Integer selectedValue = Integer.valueOf(1);
+       private Integer selectedValue = 1;
        @Override
        public int getSize() { return 11; }
        @Override
-       public Integer getElementAt(int index) { return Integer.valueOf(index + 1); }
+       public Integer getElementAt(int index) { return index + 1; }
        @Override
        public void addListDataListener(ListDataListener l) { }
        @Override
index 204c2a7..59a2001 100644 (file)
@@ -50,6 +50,6 @@ public class CapoSelecterView extends JPanel {
         * @return カポ位置
         */
        public int getCapo() {
-               return checkbox.isSelected() ? valueSelecter.getSelectedIndex()+1 : 0;
+               return checkbox.isSelected() ? (int) valueSelecter.getModel().getSelectedItem() : 0;
        }
 }
\ No newline at end of file
index d2e7589..42f77c8 100644 (file)
@@ -183,9 +183,7 @@ public class ChordDiagram extends JPanel {
                                new AdjustmentListener() {
                                        @Override
                                        public void adjustmentValueChanged(AdjustmentEvent e) {
-                                               setToolTipText(
-                                                       diagramDisplay.chordVariations.getIndexDescription()
-                                               );
+                                               setToolTipText(diagramDisplay.chordVariations.getIndexDescription());
                                        }
                                }
                        );
index d379353..8e458d1 100644 (file)
@@ -86,7 +86,7 @@ public abstract class AbstractVirtualMidiDevice implements VirtualMidiDevice {
        @Override
        public Transmitter getTransmitter() throws MidiUnavailableException {
                if( maxTransmitters == 0 ) throw new MidiUnavailableException();
-               Transmitter new_tx = new Transmitter() {
+               Transmitter newTx = new Transmitter() {
                        private Receiver rx = null;
                        @Override
                        public void close() { txList.remove(this); }
@@ -95,8 +95,8 @@ public abstract class AbstractVirtualMidiDevice implements VirtualMidiDevice {
                        @Override
                        public void setReceiver(Receiver rx) { this.rx = rx; }
                };
-               txList.add(new_tx);
-               return new_tx;
+               txList.add(newTx);
+               return newTx;
        }
        @Override
        public void sendMidiMessage(MidiMessage msg) {
index d0c7553..1ba0014 100644 (file)
@@ -1,5 +1,6 @@
 package camidion.chordhelper.mididevice;
 
+import javax.sound.midi.MidiDevice;
 import javax.sound.midi.MidiEvent;
 import javax.sound.midi.Receiver;
 import javax.sound.midi.Transmitter;
@@ -30,11 +31,11 @@ public enum MidiDeviceInOutType {
                this.description = description;
                this.shortName = shortName;
        }
-       public static MidiDeviceInOutType getValueFor(TransmitterListModel txListModel, ReceiverListModel rxListModel) {
+       public static MidiDeviceInOutType getValueFor(MidiDevice device) {
                // tx:IN rx:OUT
-               return rxListModel == null ?
-                       (txListModel == null ? MIDI_NONE : MIDI_IN) :
-                       (txListModel == null ? MIDI_OUT  : MIDI_IN_OUT);
+               return device.getMaxReceivers() == 0 ?
+                       (device.getMaxTransmitters() == 0 ? MIDI_NONE : MIDI_IN) :
+                       (device.getMaxTransmitters() == 0 ? MIDI_OUT  : MIDI_IN_OUT);
        }
        public String getDescription() { return description; }
        private String description;
index 41da29b..e0e89a4 100644 (file)
@@ -65,14 +65,14 @@ public class MidiDeviceModel {
         * MIDIデバイスからモデルを構築します。
         *
         * @param device 対象MIDIデバイス
-        * @param deviceTreeModel このMIDIデバイスモデルのマネージャー(接続相手となりうるMIDIデバイス)
+        * @param deviceTreeModel このモデルの親ツリー
         */
        public MidiDeviceModel(MidiDevice device, MidiDeviceTreeModel deviceTreeModel) {
                this.deviceTreeModel = deviceTreeModel;
                this.device = device;
                if( device.getMaxTransmitters() != 0 ) txListModel = new TransmitterListModel(this);
                if( device.getMaxReceivers() != 0 ) rxListModel = new ReceiverListModel(this);
-               ioType = MidiDeviceInOutType.getValueFor(txListModel, rxListModel);
+               ioType = MidiDeviceInOutType.getValueFor(device);
                treePath = new TreePath(new Object[] {deviceTreeModel, ioType ,this});
        }
        /**
index d76da27..97f8dbb 100644 (file)
@@ -35,8 +35,11 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
        @Override
        public String toString() { return "MIDI devices"; }
 
-       // MIDIデバイスモデルリストとツリー
        protected List<MidiDeviceModel> deviceModelList = new Vector<>();
+       @Override
+       public int size() { return deviceModelList.size(); }
+       @Override
+       public MidiDeviceModel get(int index) { return deviceModelList.get(index); }
        protected Map<MidiDeviceInOutType, List<MidiDeviceModel>> deviceModelTree; {
                deviceModelTree = new EnumMap<>(MidiDeviceInOutType.class);
                deviceModelTree.put(MidiDeviceInOutType.MIDI_OUT, new ArrayList<>());
@@ -44,68 +47,30 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                deviceModelTree.put(MidiDeviceInOutType.MIDI_IN_OUT, new ArrayList<>());
        };
        /**
-        * MIDIデバイスモデルを追加します。
-        *
+        * {@link #add()}の非public版です。
         * @param dm 追加するMIDIデバイスモデル
-        * @return 呼出しの結果としてこのリストが変更された場合はtrue
+        * @return true({@link AbstractList#add()}と同じ)
         */
-       protected boolean addDeviceModel(MidiDeviceModel dm) {
+       protected boolean addInternally(MidiDeviceModel dm) {
                if( ! deviceModelList.add(dm) ) return false;
-               deviceModelTree.get(dm.getInOutType()).add(dm); return true;
-       }
-       /**
-        * MIDIデバイス情報をモデルとして追加します。
-        *
-        * @param info 追加するMIDIデバイス情報({@link MidiDevice.Info})
-        * @return 呼出しの結果としてこのリストが変更された場合はtrue
-        * @throws MidiUnavailableException {@link MidiDeviceModel#MidiDeviceModel(MidiDevice.Info, MidiDeviceTreeModel) MidiDeviceModelコンストラクタ}からの例外
-        */
-       protected boolean addDeviceModel(MidiDevice.Info info) throws MidiUnavailableException {
-               return addDeviceModel(new MidiDeviceModel(info, this));
-       }
-       /**
-        * リストとツリーモデルから、指定されたMIDIデバイスモデル(複数指定可)を除去します。
-        *
-        * @param deviceModelsToRemove 除去したいMIDIデバイスモデル
-        * @return 指定されたMIDIデバイスモデルがこのリストに含まれていた場合はtrue
-        */
-       protected boolean removeDeviceModels(Collection<MidiDeviceModel> deviceModelsToRemove) {
-               if( ! deviceModelList.removeAll(deviceModelsToRemove) ) return false;
-               for( MidiDeviceModel dm : deviceModelsToRemove )
-                       deviceModelTree.get(dm.getInOutType()).remove(dm);
+               deviceModelTree.get(dm.getInOutType()).add(dm);
                return true;
        }
        /**
-        * リスト、ツリーモデル、接続マップから、指定されたMIDIデバイスモデル(複数指定可)を除去します。
-        *
-        * @param deviceModelsToRemove 除去したいMIDIデバイスモデル
-        * @param rxToTxConnections MIDIデバイスモデル接続マップ({@link #disconnectAllDevices()}の戻り値)
-        * @return 指定されたMIDIデバイスモデルがこのリストに含まれていた場合はtrue
+        * {@link #removeAll()}の非public版です。
+        * @param c 削除する要素のコレクション
+        * @return {@link AbstractList#removeAll()}と同じ
         */
-       protected boolean removeDeviceModels(
-                       Collection<MidiDeviceModel> deviceModelsToRemove,
-                       Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections) {
-               if( ! removeDeviceModels(deviceModelsToRemove) ) return false;
-               Set<MidiDeviceModel> rxModels = rxToTxConnections.keySet();
-               rxModels.removeAll(deviceModelsToRemove);
-               for( MidiDeviceModel m : rxModels )
-                       rxToTxConnections.get(m).removeAll(deviceModelsToRemove);
+       protected boolean removeAllInternally(Collection<?> c) {
+               if( ! deviceModelList.removeAll(c) ) return false;
+               for( Object o : c ) {
+                       if( o instanceof MidiDeviceModel ) {
+                               MidiDeviceInOutType ioType = ((MidiDeviceModel)o).getInOutType();
+                               deviceModelTree.get(ioType).remove(o);
+                       }
+               }
                return true;
        }
-
-       /**
-        * このMIDIデバイスツリーモデルに登録されているMIDIシーケンサーモデルを返します。
-        * @return MIDIシーケンサーモデル
-        */
-       public MidiSequencerModel getSequencerModel() { return sequencerModel; }
-       protected MidiSequencerModel sequencerModel;
-       //
-       // リスト用インターフェース
-       @Override
-       public MidiDeviceModel get(int index) { return deviceModelList.get(index); }
-       @Override
-       public int size() { return deviceModelList.size(); }
-       //
        // ツリーモデル用インターフェース
        @Override
        public Object getRoot() { return this; }
@@ -183,6 +148,13 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
        }
 
        /**
+        * このMIDIデバイスツリーモデルに登録されているMIDIシーケンサーモデルを返します。
+        * @return MIDIシーケンサーモデル
+        */
+       public MidiSequencerModel getSequencerModel() { return sequencerModel; }
+       protected MidiSequencerModel sequencerModel;
+
+       /**
         * 引数で与えられたGUI仮想MIDIデバイスと、{@link #getMidiDeviceInfo()}から取得したMIDIデバイス情報から、
         * MIDIデバイスツリーモデルを初期構築します。
         *
@@ -190,9 +162,9 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         */
        public MidiDeviceTreeModel(VirtualMidiDevice guiVirtualDevice) {
                MidiDeviceModel guiModel = new MidiDeviceModel(guiVirtualDevice, this);
-               addDeviceModel(guiModel);
+               addInternally(guiModel);
                try {
-                       addDeviceModel(sequencerModel = new MidiSequencerModel(MidiSystem.getSequencer(false), this));
+                       addInternally(sequencerModel = new MidiSequencerModel(MidiSystem.getSequencer(false), this));
                } catch( MidiUnavailableException e ) {
                        System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
                        e.printStackTrace();
@@ -211,7 +183,7 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                        if( device instanceof Sequencer ) continue; // シーケンサはすでに取得済み
                        if( device instanceof Synthesizer ) { // Java内蔵シンセサイザ
                                try {
-                                       addDeviceModel(synthModel = new MidiDeviceModel(MidiSystem.getSynthesizer(), this));
+                                       addInternally(synthModel = new MidiDeviceModel(MidiSystem.getSynthesizer(), this));
                                } catch( MidiUnavailableException e ) {
                                        System.out.println(ChordHelperApplet.VersionInfo.NAME +
                                                        " : Java internal MIDI synthesizer unavailable");
@@ -227,7 +199,7 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                        // 最初の MIDI IN(USB MIDI インターフェースにつながったMIDIキーボードなど)
                        if( firstMidiInModel == null && m.getTransmitterListModel() != null ) firstMidiInModel = m;
                        //
-                       addDeviceModel(m);
+                       addInternally(m);
                }
                // 開くMIDIデバイスモデルの一覧を作成
                //
@@ -340,12 +312,15 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                        toRemove.add(m);
                }
                // 削除されたデバイスのモデルを除去
-               removeDeviceModels(toRemove, rxToTxConnections);
-               //
+               if( removeAllInternally(toRemove) ) {
+                       Set<MidiDeviceModel> rxModels = rxToTxConnections.keySet();
+                       rxModels.removeAll(toRemove);
+                       for( MidiDeviceModel m : rxModels ) rxToTxConnections.get(m).removeAll(toRemove);
+               }
                // 追加されたデバイスのモデルを登録
                for( MidiDevice.Info info : toAdd ) {
                        try {
-                               addDeviceModel(info);
+                               addInternally(new MidiDeviceModel(info, this));
                        } catch( MidiUnavailableException e ) {
                                e.printStackTrace();
                        }
index 6efbe90..be1d172 100644 (file)
@@ -69,7 +69,6 @@ public class MidiDeviceTreeView extends JTree {
                                return this;
                        }
                });
-               //
                // ツリーノードのToolTipを有効化
                ToolTipManager.sharedInstance().registerComponent(this);
                //
index ee13697..9b5d273 100644 (file)
@@ -31,6 +31,10 @@ import camidion.chordhelper.midieditor.SequencerSpeedSlider;
  */
 public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeModel {
        /**
+        * 再生位置スライダーモデルの最小単位 [μ秒]
+        */
+       public static final long RESOLUTION_MICROSECOND = 1000L;
+       /**
         * MIDIシーケンサモデルを構築します。
         * @param sequencer シーケンサーMIDIデバイス
         * @param deviceModelTree 親のMIDIデバイスツリーモデル
@@ -158,7 +162,7 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
                return usLength < 0 ? 0x100000000L + usLength : usLength ;
        }
        @Override
-       public int getMaximum() { return (int)(getMicrosecondLength()/1000L); }
+       public int getMaximum() { return (int)(getMicrosecondLength()/RESOLUTION_MICROSECOND); }
        @Override
        public void setMaximum(int newMaximum) {}
        @Override
@@ -178,10 +182,10 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
                return usPosition < 0 ? 0x100000000L + usPosition : usPosition ;
        }
        @Override
-       public int getValue() { return (int)(getMicrosecondPosition()/1000L); }
+       public int getValue() { return (int)(getMicrosecondPosition()/RESOLUTION_MICROSECOND); }
        @Override
        public void setValue(int newValue) {
-               getSequencer().setMicrosecondPosition(1000L * (long)newValue);
+               getSequencer().setMicrosecondPosition(RESOLUTION_MICROSECOND * (long)newValue);
                fireStateChanged();
        }
        /**
@@ -196,7 +200,7 @@ public class MidiSequencerModel extends MidiDeviceModel implements BoundedRangeM
        }
        @Override
        public void setRangeProperties(int value, int extent, int min, int max, boolean valueIsAdjusting) {
-               getSequencer().setMicrosecondPosition(1000L * (long)value);
+               getSequencer().setMicrosecondPosition(RESOLUTION_MICROSECOND * (long)value);
                setValueIsAdjusting(valueIsAdjusting);
                fireStateChanged();
        }
index fbb2732..5083469 100644 (file)
@@ -10,11 +10,12 @@ import javax.swing.Box;
 import javax.swing.BoxLayout;
 import javax.swing.JButton;
 import javax.swing.JDialog;
-import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JTextArea;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
 
 import camidion.chordhelper.ButtonIcon;
 import camidion.chordhelper.ChordHelperApplet;
@@ -22,69 +23,47 @@ import camidion.chordhelper.ChordHelperApplet;
 /**
  * Base64テキスト入力ダイアログ
  */
-public class Base64Dialog extends JDialog {
-       private Base64TextArea base64TextArea = new Base64TextArea(8,56);
+public class Base64Dialog extends JDialog implements DocumentListener {
+       public static final Pattern HEADER_PATTERN = Pattern.compile("^.*:.*$", Pattern.MULTILINE);
+       private JTextArea base64TextArea = new JTextArea(8,56);
        private MidiSequenceEditorDialog midiEditor;
+       private void error(String message) {
+               JOptionPane.showMessageDialog(base64TextArea, (Object)message,
+                               ChordHelperApplet.VersionInfo.NAME, JOptionPane.WARNING_MESSAGE);
+               base64TextArea.requestFocusInWindow();
+       }
        /**
         * Base64デコードアクション
         */
-       public Action addBase64Action = new AbstractAction(
-               "Base64 Decode & Add to PlayList",
-               new ButtonIcon(ButtonIcon.EJECT_ICON)
-       ) {
+       public Action addBase64Action = new AbstractAction("Add to PlayList", new ButtonIcon(ButtonIcon.EJECT_ICON)) {
                { putValue(Action.SHORT_DESCRIPTION, "Base64デコードして、プレイリストへ追加"); }
                @Override
                public void actionPerformed(ActionEvent event) {
-                       String message = null;
+                       byte[] midiData = null;
+                       try {
+                               midiData = getMIDIData();
+                       } catch(Exception e) {
+                               e.printStackTrace();
+                               error("Base64デコードに失敗しました。\n"+e);
+                               return;
+                       }
                        try {
-                               byte[] data = getMIDIData();
-                               if( data == null || data.length == 0 ) {
-                                       message = "No data on textbox - データが入力されていません。";
-                               } else {
-                                       midiEditor.sequenceListTable.getModel().addSequence(data, null);
-                                       setVisible(false);
-                               }
+                               midiEditor.sequenceListTable.getModel().addSequence(midiData, null);
                        } catch(Exception e) {
                                e.printStackTrace();
-                               message = "Base64デコードまたはMIDIデータの読み込みに失敗しました。\n"+e;
+                               error("Base64デコードされたデータが正しいMIDI形式になっていません。\n"+e);
+                               return;
                        }
-                       if( message == null ) return;
-                       JOptionPane.showMessageDialog(base64TextArea, (Object)message,
-                                       ChordHelperApplet.VersionInfo.NAME, JOptionPane.WARNING_MESSAGE);
-                       base64TextArea.requestFocusInWindow();
+                       setVisible(false);
                }
        };
        /**
         * Base64テキストクリアアクション
         */
-       public Action clearAction = new AbstractAction("Clear") {
+       public Action clearAction = new AbstractAction("Clear", new ButtonIcon(ButtonIcon.X_ICON)) {
                @Override
-               public void actionPerformed(ActionEvent e) {
-                       base64TextArea.setText(null);
-               }
+               public void actionPerformed(ActionEvent e) { base64TextArea.setText(null); }
        };
-       private static class Base64TextArea extends JTextArea {
-               private static final Pattern headerLineFormat =
-                       Pattern.compile( "^.*:.*$", Pattern.MULTILINE );
-               public Base64TextArea(int rows, int columns) {
-                       super(rows,columns);
-               }
-               public byte[] getBinary() {
-                       String text = headerLineFormat.matcher(getText()).replaceAll("");
-                       return Base64.getMimeDecoder().decode(text.getBytes());
-               }
-               public void setBinary(byte[] binary_data, String content_type, String filename) {
-                       if( binary_data != null && binary_data.length > 0 ) {
-                               String header = "";
-                               if( content_type != null && filename != null ) {
-                                       header += "Content-Type: " + content_type + "; name=\"" + filename + "\"\n";
-                                       header += "Content-Transfer-Encoding: base64\n";
-                                       header += "\n";
-                               }
-                               setText(header + Base64.getMimeEncoder().encodeToString(binary_data) + "\n");
-                       }
-               }
-       }
        /**
         * Base64テキスト入力ダイアログを構築します。
         * @param midiEditor 親画面となるMIDIエディタ
@@ -96,7 +75,6 @@ public class Base64Dialog extends JDialog {
                        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
                        add(new JPanel() {{
                                setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
-                               add(new JLabel("Base64-encoded MIDI sequence:"));
                                add(Box.createRigidArea(new Dimension(10, 0)));
                                add(new JButton(addBase64Action){{setMargin(ChordHelperApplet.ZERO_INSETS);}});
                                add(new JButton(clearAction){{setMargin(ChordHelperApplet.ZERO_INSETS);}});
@@ -104,38 +82,58 @@ public class Base64Dialog extends JDialog {
                        add(new JScrollPane(base64TextArea));
                }});
                setBounds( 300, 250, 660, 300 );
+               base64TextArea.setToolTipText("Paste Base64-encoded MIDI sequence here");
+               base64TextArea.getDocument().addDocumentListener(this);
+               addBase64Action.setEnabled(false);
+               clearAction.setEnabled(false);
+       }
+       @Override
+       public void insertUpdate(DocumentEvent e) {
+               addBase64Action.setEnabled(true);
+               clearAction.setEnabled(true);
        }
+       @Override
+       public void removeUpdate(DocumentEvent e) {
+               if( e.getDocument().getLength() > 0 ) return;
+               addBase64Action.setEnabled(false);
+               clearAction.setEnabled(false);
+       }
+       @Override
+       public void changedUpdate(DocumentEvent e) { }
        /**
         * バイナリー形式でMIDIデータを返します。
         * @return バイナリー形式のMIDIデータ
         * @throws IllegalArgumentException 入力されているテキストが有効なBase64スキームになっていない場合
         */
        public byte[] getMIDIData() {
-               return base64TextArea.getBinary();
+               String body = HEADER_PATTERN.matcher(base64TextArea.getText()).replaceAll("");
+               return Base64.getMimeDecoder().decode(body.getBytes());
        }
        /**
         * バイナリー形式のMIDIデータを設定します。
         * @param midiData バイナリー形式のMIDIデータ
         */
-       public void setMIDIData( byte[] midiData ) {
-               base64TextArea.setBinary(midiData, null, null);
-       }
+       public void setMIDIData(byte[] midiData) { setMIDIData(midiData, null); }
        /**
         * バイナリー形式のMIDIデータを、ファイル名をつけて設定します。
         * @param midiData バイナリー形式のMIDIデータ
         * @param filename ファイル名
         */
-       public void setMIDIData( byte[] midiData, String filename ) {
-               base64TextArea.setBinary(midiData, "audio/midi", filename);
+       public void setMIDIData(byte[] midiData, String filename) {
+               if( midiData == null || midiData.length == 0 ) return;
+               if( filename == null ) filename = "";
+               String text =
+                               "Content-Type: audio/midi; name=\"" + filename + "\"\n"
+                                               + "Content-Transfer-Encoding: base64\n\n" +
+                                               Base64.getMimeEncoder().encodeToString(midiData) + "\n";
+               base64TextArea.setText(text);
                base64TextArea.selectAll();
        }
        /**
         * Base64形式でMIDIデータを返します。
         * @return  Base64形式のMIDIデータ
         */
-       public String getBase64Data() {
-               return base64TextArea.getText();
-       }
+       public String getBase64Data() { return base64TextArea.getText(); }
        /**
         * Base64形式のMIDIデータを設定します。
         * @param base64Data Base64形式のMIDIデータ