OSDN Git Service

・シーケンサへのシーケンスロード時の例外をダイアログ表示する実装を追加
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sun, 29 May 2016 14:57:29 +0000 (23:57 +0900)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sun, 29 May 2016 14:57:29 +0000 (23:57 +0900)
・リファクタリング

src/camidion/chordhelper/ChordHelperApplet.java
src/camidion/chordhelper/mididevice/MidiSequencerModel.java
src/camidion/chordhelper/midieditor/MidiSequenceEditor.java
src/camidion/chordhelper/midieditor/NewSequenceDialog.java
src/camidion/chordhelper/midieditor/PlaylistTableModel.java

index 9982074..7002c63 100644 (file)
@@ -26,6 +26,7 @@ import java.util.Arrays;
 import javax.sound.midi.InvalidMidiDataException;
 import javax.sound.midi.MetaEventListener;
 import javax.sound.midi.MetaMessage;
+import javax.sound.midi.Sequence;
 import javax.sound.midi.Sequencer;
 import javax.swing.AbstractAction;
 import javax.swing.Action;
@@ -100,8 +101,9 @@ public class ChordHelperApplet extends JApplet {
         * 指定された小節数の曲を、乱数で自動作曲してプレイリストへ追加します。
         * @param measureLength 小節数
         * @return 追加先のインデックス値(0から始まる)。追加できなかったときは -1
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public int addRandomSongToPlaylist(int measureLength) {
+       public int addRandomSongToPlaylist(int measureLength) throws InvalidMidiDataException {
                NewSequenceDialog d = midiEditor.newSequenceDialog;
                d.setRandomChordProgression(measureLength);
                return playlistModel.addSequenceAndPlay(d.getMidiSequence());
@@ -157,14 +159,18 @@ public class ChordHelperApplet extends JApplet {
        /**
         * プレイリスト上で現在選択されているMIDIシーケンスを、
         * シーケンサへロードして再生します。
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public void play() { play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex()); }
+       public void play() throws InvalidMidiDataException { play(playlistModel.sequenceListSelectionModel.getMinSelectionIndex()); }
        /**
         * 指定されたインデックス値が示すプレイリスト上のMIDIシーケンスを、
         * シーケンサへロードして再生します。
         * @param index インデックス値(0から始まる)
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public void play(int index) { playlistModel.loadToSequencer(index); sequencerModel.start(); }
+       public void play(int index) throws InvalidMidiDataException {
+               playlistModel.loadToSequencer(index); sequencerModel.start();
+       }
        /**
         * シーケンサが実行中かどうかを返します。
         * {@link Sequencer#isRunning()} の戻り値をそのまま返します。
@@ -279,7 +285,7 @@ public class ChordHelperApplet extends JApplet {
         */
        public static class VersionInfo {
                public static final String      NAME = "MIDI Chord Helper";
-               public static final String      VERSION = "Ver.20160528.1";
+               public static final String      VERSION = "Ver.20160529.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/";
@@ -423,26 +429,26 @@ public class ChordHelperApplet extends JApplet {
                                }
                                public void chordChanged() { chordOn(); }
                        });
+                       capoSelecter.checkbox.addItemListener(new ItemListener() {
+                               public void itemStateChanged(ItemEvent e) {
+                                       chordOn();
+                                       keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
+                                       chordDiagram.clear();
+                               }
+                       });
+                       capoSelecter.valueSelecter.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       chordOn();
+                                       keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
+                                       chordDiagram.clear();
+                               }
+                       });
                }};
                keysigLabel = new KeySignatureLabel() {{
                        addMouseListener(new MouseAdapter() {
                                public void mousePressed(MouseEvent e) { chordMatrix.setKeySignature(getKey()); }
                        });
                }};
-               chordMatrix.capoSelecter.checkbox.addItemListener(new ItemListener() {
-                       public void itemStateChanged(ItemEvent e) {
-                               chordOn();
-                               keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
-                               chordDiagram.clear();
-                       }
-               });
-               chordMatrix.capoSelecter.valueSelecter.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               chordOn();
-                               keyboardPanel.keyboardCenterPanel.keyboard.chordDisplay.clear();
-                               chordDiagram.clear();
-                       }
-               });
                keyboardPanel = new MidiKeyboardPanel(chordMatrix) {{
                        keyboardCenterPanel.keyboard.addPianoKeyboardListener(new PianoKeyboardAdapter() {
                                @Override
@@ -704,7 +710,11 @@ public class ChordHelperApplet extends JApplet {
                System.gc();
                if( midi_url != null ) {
                        addToPlaylist(midi_url);
-                       play();
+                       try {
+                               play();
+                       } catch (InvalidMidiDataException ex) {
+                               ex.printStackTrace();
+                       }
                }
        }
        @Override
index 3269f52..8e774ad 100644 (file)
@@ -257,9 +257,11 @@ public class MidiSequencerModel extends MidiTransceiverListModel implements Boun
         * MIDIトラックリストテーブルモデルをこのシーケンサーモデルにセットします。
         * nullを指定してアンセットすることもできます。
         * @param sequenceTableModel MIDIトラックリストテーブルモデル
-        * @return 成功したらtrue
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public boolean setSequenceTrackListTableModel(SequenceTrackListTableModel sequenceTableModel) {
+       public void setSequenceTrackListTableModel(SequenceTrackListTableModel sequenceTableModel)
+               throws InvalidMidiDataException
+       {
                // javax.sound.midi:Sequencer.setSequence() のドキュメントにある
                // 「このメソッドは、Sequencer が閉じている場合でも呼び出すことができます。 」
                // という記述は、null をセットする場合には当てはまらない。
@@ -267,14 +269,7 @@ public class MidiSequencerModel extends MidiTransceiverListModel implements Boun
                // この現象を回避するため、あらかじめチェックしてから setSequence() を呼び出している。
                //
                if( sequenceTableModel != null || getSequencer().isOpen() ) {
-                       Sequence sequence = null;
-                       if( sequenceTableModel != null ) sequence = sequenceTableModel.getSequence();
-                       try {
-                               getSequencer().setSequence(sequence);
-                       } catch ( InvalidMidiDataException e ) {
-                               e.printStackTrace();
-                               return false;
-                       }
+                       getSequencer().setSequence(sequenceTableModel == null ? null : sequenceTableModel.getSequence());
                }
                if( this.sequenceTableModel != null ) {
                        this.sequenceTableModel.fireTableDataChanged();
@@ -284,9 +279,7 @@ public class MidiSequencerModel extends MidiTransceiverListModel implements Boun
                }
                this.sequenceTableModel = sequenceTableModel;
                fireStateChanged();
-               return true;
        }
-
        /**
         * 小節単位で位置を移動します。
         * @param measureOffset 何小節進めるか(戻したいときは負数を指定)
index 98b8cd5..944a81b 100644 (file)
@@ -35,6 +35,7 @@ import javax.sound.midi.InvalidMidiDataException;
 import javax.sound.midi.MidiChannel;
 import javax.sound.midi.MidiEvent;
 import javax.sound.midi.MidiMessage;
+import javax.sound.midi.Sequence;
 import javax.sound.midi.Sequencer;
 import javax.sound.midi.ShortMessage;
 import javax.swing.AbstractAction;
@@ -134,8 +135,7 @@ public class MidiSequenceEditor extends JDialog {
                public void drop(DropTargetDropEvent event) {
                        event.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                        try {
-                               int action = event.getDropAction();
-                               if ( (action & DnDConstants.ACTION_COPY_OR_MOVE) != 0 ) {
+                               if ( (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0 ) {
                                        Transferable t = event.getTransferable();
                                        if( t.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ) {
                                                loadAndPlay((List<File>)t.getTransferData(DataFlavor.javaFileListFlavor));
@@ -156,6 +156,7 @@ public class MidiSequenceEditor extends JDialog {
         * すでに再生されていた場合、このエディタダイアログを表示します。
         *
         * @param fileList 読み込むMIDIファイルのリスト
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         * @see #loadAndPlay(File)
         */
        public void loadAndPlay(List<File> fileList) {
@@ -169,15 +170,20 @@ public class MidiSequenceEditor extends JDialog {
                        showError(e.getMessage());
                        e.printStackTrace();
                }
-               MidiSequencerModel sequencerModel = playlist.sequencerModel;
-               if( sequencerModel.getSequencer().isRunning() ) {
+               if( playlist.sequencerModel.getSequencer().isRunning() ) {
                        String command = (String)openAction.getValue(Action.NAME);
                        openAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, command));
                        return;
                }
                if( indexOfAddedTop >= 0 ) {
-                       playlist.loadToSequencer(indexOfAddedTop);
-                       sequencerModel.start();
+                       try {
+                               playlist.loadToSequencer(indexOfAddedTop);
+                       } catch (InvalidMidiDataException ex) {
+                               ex.printStackTrace();
+                               showError(ex.getMessage());
+                               return;
+                       }
+                       playlist.sequencerModel.start();
                }
        }
        /**
@@ -185,9 +191,12 @@ public class MidiSequenceEditor extends JDialog {
         * すでに再生されていた場合、このエディタダイアログを表示します。
         *
         * @param file 読み込むMIDIファイル
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         * @see #loadAndPlay(List) loadAndPlay(List&lt;File&gt;)
         */
-       public void loadAndPlay(File file) { loadAndPlay(Arrays.asList(file)); }
+       public void loadAndPlay(File file) throws InvalidMidiDataException {
+               loadAndPlay(Arrays.asList(file));
+       }
 
        private static final Insets ZERO_INSETS = new Insets(0,0,0,0);
        private static final Icon deleteIcon = new ButtonIcon(ButtonIcon.X_ICON);
@@ -305,9 +314,7 @@ public class MidiSequenceEditor extends JDialog {
                /**
                 * 時間位置表示セルエディタ(ダブルクリック専用)
                 */
-               private class PositionCellEditor extends AbstractCellEditor
-                       implements TableCellEditor
-               {
+               private class PositionCellEditor extends AbstractCellEditor implements TableCellEditor {
                        public PositionCellEditor() {
                                int column = PlaylistTableModel.Column.POSITION.ordinal();
                                TableColumn tc = getColumnModel().getColumn(column);
@@ -334,10 +341,14 @@ public class MidiSequenceEditor extends JDialog {
                         */
                        @Override
                        public Component getTableCellEditorComponent(
-                               JTable table, Object value, boolean isSelected,
-                               int row, int column
+                               JTable table, Object value, boolean isSelected, int row, int column
                        ) {
-                               getModel().loadToSequencer(row);
+                               try {
+                                       getModel().loadToSequencer(row);
+                               } catch (InvalidMidiDataException ex) {
+                                       ex.printStackTrace();
+                                       showError(ex.getMessage());
+                               }
                                fireEditingStopped();
                                return null;
                        }
@@ -404,7 +415,12 @@ public class MidiSequenceEditor extends JDialog {
                                fireEditingStopped();
                                PlaylistTableModel model = getModel();
                                if( model.getSequenceList().get(row).isOnSequencer() ) return playButton;
-                               model.loadToSequencer(row);
+                               try {
+                                       model.loadToSequencer(row);
+                               } catch (InvalidMidiDataException ex) {
+                                       ex.printStackTrace();
+                                       showError(ex.getMessage());
+                               }
                                return null;
                        }
                        @Override
@@ -436,7 +452,7 @@ public class MidiSequenceEditor extends JDialog {
                        "Delete selected MIDI sequence - 選択した曲をプレイリストから削除"
                ) {
                        @Override
-                       public void actionPerformed(ActionEvent e) {
+                       public void actionPerformed(ActionEvent event) {
                                PlaylistTableModel model = getModel();
                                if( midiFileChooser != null ) {
                                        if( model.getSelectedSequenceModel().isModified() ) {
@@ -446,7 +462,12 @@ public class MidiSequenceEditor extends JDialog {
                                                if( ! confirm(message) ) return;
                                        }
                                }
-                               model.removeSelectedSequence();
+                               try {
+                                       model.removeSelectedSequence();
+                               } catch (InvalidMidiDataException ex) {
+                                       ex.printStackTrace();
+                                       showError(ex.getMessage());
+                               }
                        }
                };
                /**
@@ -492,7 +513,12 @@ public class MidiSequenceEditor extends JDialog {
                                @Override
                                public void actionPerformed(ActionEvent event) {
                                        if( showOpenDialog((Component)event.getSource()) != JFileChooser.APPROVE_OPTION ) return;
-                                       loadAndPlay(getSelectedFile());
+                                       try {
+                                               loadAndPlay(getSelectedFile());
+                                       } catch (InvalidMidiDataException ex) {
+                                               ex.printStackTrace();
+                                               showError(ex.getMessage());
+                                       }
                                }
                        };
                };
@@ -1123,7 +1149,7 @@ public class MidiSequenceEditor extends JDialog {
                this.outputMidiDevice = outputMidiDevice;
                sequenceListTable = new SequenceListTable(playlistTableModel);
                trackListTable = new TrackListTable(
-                       new SequenceTrackListTableModel(sequenceListTable.getModel(), null, null)
+                       new SequenceTrackListTableModel(playlistTableModel, null, null)
                );
                eventListTable = new EventListTable(new TrackEventListTableModel(trackListTable.getModel(), null));
                newSequenceDialog = new NewSequenceDialog(playlistTableModel, outputMidiDevice);
@@ -1140,9 +1166,7 @@ public class MidiSequenceEditor extends JDialog {
                                add(new JButton(newSequenceDialog.openAction) {{ setMargin(ZERO_INSETS); }});
                                if( sequenceListTable.midiFileChooser != null ) {
                                        add( Box.createRigidArea(new Dimension(5, 0)) );
-                                       add(new JButton(sequenceListTable.midiFileChooser.openMidiFileAction) {{
-                                               setMargin(ZERO_INSETS);
-                                       }});
+                                       add(new JButton(sequenceListTable.midiFileChooser.openMidiFileAction) {{ setMargin(ZERO_INSETS); }});
                                }
                                if(sequenceListTable.base64EncodeAction != null) {
                                        add(Box.createRigidArea(new Dimension(5, 0)));
@@ -1155,9 +1179,7 @@ public class MidiSequenceEditor extends JDialog {
                                add(new JButton(playlistTableModel.moveToBottomAction) {{ setMargin(ZERO_INSETS); }});
                                if( sequenceListTable.midiFileChooser != null ) {
                                        add(Box.createRigidArea(new Dimension(5, 0)));
-                                       add(new JButton(sequenceListTable.midiFileChooser.saveMidiFileAction) {{
-                                               setMargin(ZERO_INSETS);
-                                       }});
+                                       add(new JButton(sequenceListTable.midiFileChooser.saveMidiFileAction) {{ setMargin(ZERO_INSETS); }});
                                }
                                add( Box.createRigidArea(new Dimension(5, 0)) );
                                add(new JButton(sequenceListTable.deleteSequenceAction) {{ setMargin(ZERO_INSETS); }});
index 73f4253..210edf0 100644 (file)
@@ -17,6 +17,7 @@ import java.awt.event.MouseListener;
 import java.util.ArrayList;
 import java.util.Vector;
 
+import javax.sound.midi.InvalidMidiDataException;
 import javax.sound.midi.MidiChannel;
 import javax.sound.midi.Sequence;
 import javax.swing.AbstractAction;
@@ -28,6 +29,7 @@ import javax.swing.JComboBox;
 import javax.swing.JComponent;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JSpinner;
@@ -99,13 +101,19 @@ public class NewSequenceDialog extends JDialog {
         * MIDIシーケンス生成アクション
         */
        public Action generateAction = new AbstractAction(
-               "Generate & Add to PlayList",
-               new ButtonIcon(ButtonIcon.EJECT_ICON)
+               "Generate & Add to PlayList", new ButtonIcon(ButtonIcon.EJECT_ICON)
        ) {
                @Override
-               public void actionPerformed(ActionEvent e) {
-                       playlist.addSequenceAndPlay(getMidiSequence());
-                       NewSequenceDialog.this.setVisible(false);
+               public void actionPerformed(ActionEvent event) {
+                       try {
+                               playlist.addSequenceAndPlay(getMidiSequence());
+                       } catch (InvalidMidiDataException ex) {
+                               ex.printStackTrace();
+                               JOptionPane.showMessageDialog(
+                                       NewSequenceDialog.this, ex.getMessage(),
+                                       ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
+                       }
+                       setVisible(false);
                }
        };
        /**
index f0fc9ad..35d49ab 100644 (file)
@@ -18,10 +18,12 @@ import javax.sound.midi.MetaEventListener;
 import javax.sound.midi.MetaMessage;
 import javax.sound.midi.MidiSystem;
 import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
 import javax.swing.AbstractAction;
 import javax.swing.Action;
 import javax.swing.DefaultListSelectionModel;
 import javax.swing.Icon;
+import javax.swing.JOptionPane;
 import javax.swing.ListSelectionModel;
 import javax.swing.SwingUtilities;
 import javax.swing.event.ChangeEvent;
@@ -31,6 +33,7 @@ import javax.swing.event.ListSelectionListener;
 import javax.swing.table.AbstractTableModel;
 
 import camidion.chordhelper.ButtonIcon;
+import camidion.chordhelper.ChordHelperApplet;
 import camidion.chordhelper.mididevice.MidiSequencerModel;
 import camidion.chordhelper.music.ChordProgression;
 
@@ -113,7 +116,7 @@ public class PlaylistTableModel extends AbstractTableModel {
        private void goNext() {
                // とりあえず曲の先頭へ戻る
                sequencerModel.getSequencer().setMicrosecondPosition(0);
-               if( (Boolean)toggleRepeatAction.getValue(Action.SELECTED_KEY) || loadNext(1)) {
+               if( (Boolean)toggleRepeatAction.getValue(Action.SELECTED_KEY) || loadNext(1) ) {
                        // リピートモードのときはもう一度同じ曲を、
                        // そうでない場合は次の曲を再生開始
                        sequencerModel.start();
@@ -340,9 +343,7 @@ public class PlaylistTableModel extends AbstractTableModel {
                        this.preferredWidth = preferredWidth;
                }
                public boolean isCellEditable() { return false; }
-               public Object getValueOf(SequenceTrackListTableModel sequenceModel) {
-                       return "";
-               }
+               public Object getValueOf(SequenceTrackListTableModel sequenceModel) { return ""; }
        }
 
        @Override
@@ -496,8 +497,9 @@ public class PlaylistTableModel extends AbstractTableModel {
         * シーケンサーが停止中の場合、追加したシーケンスから再生を開始します。
         * @param sequence MIDIシーケンス
         * @return 追加先インデックス(先頭が 0)
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public int addSequenceAndPlay(Sequence sequence) {
+       public int addSequenceAndPlay(Sequence sequence) throws InvalidMidiDataException {
                int lastIndex = addSequence(sequence,"");
                if( ! sequencerModel.getSequencer().isRunning() ) {
                        loadToSequencer(lastIndex);
@@ -578,26 +580,29 @@ public class PlaylistTableModel extends AbstractTableModel {
        /**
         * 選択されたシーケンスを除去します。
         * 除去されたシーケンスがシーケンサーにロード済みの場合、アンロードします。
+        *
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public void removeSelectedSequence() {
+       public void removeSelectedSequence() throws InvalidMidiDataException {
                if( sequenceListSelectionModel.isSelectionEmpty() ) return;
                int selectedIndex = sequenceListSelectionModel.getMinSelectionIndex();
-               if( sequenceList.remove(selectedIndex).isOnSequencer() )
-                       sequencerModel.setSequenceTrackListTableModel(null);
+               if( ! sequenceList.remove(selectedIndex).isOnSequencer() ) return;
+               sequencerModel.setSequenceTrackListTableModel(null);
                fireTableRowsDeleted(selectedIndex, selectedIndex);
        }
        /**
-        * 指定したインデックス位置のシーケンスをシーケンサーにロードします。
-        * すでに同じIDのシーケンスがロードされていた場合はスキップします。
-        * @param index シーケンスのインデックス位置(-1 を指定するとアンロードされます)
+        * テーブル内の指定したインデックス位置にあるシーケンスをシーケンサーにロードします。
+        * インデックスに -1 を指定するとアンロードされます。
+        * 変更点がある場合、リスナー(テーブルビュー)に通知します。
+        *
+        * @param index ロードするシーケンスのインデックス位置、アンロードするときは -1
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
-       public void loadToSequencer(int index) {
+       public void loadToSequencer(int index) throws InvalidMidiDataException {
                SequenceTrackListTableModel oldSeq = sequencerModel.getSequenceTrackListTableModel();
                SequenceTrackListTableModel newSeq = (index < 0 ? null : sequenceList.get(index));
-               if(oldSeq == newSeq) return;
+               if( oldSeq == newSeq ) return;
                sequencerModel.setSequenceTrackListTableModel(newSeq);
-               //
-               // 変更点をテーブルビューに通知して再表示してもらう
                int columnIndices[] = {
                        Column.PLAY.ordinal(),
                        Column.POSITION.ordinal(),
@@ -621,13 +626,22 @@ public class PlaylistTableModel extends AbstractTableModel {
        /**
         * 引数で示された数だけ次へ進めたシーケンスをロードします。
         * @param offset 進みたいシーケンス数
-        * @return 成功したらtrue
+        * @return true:ロード成功、false:これ以上進めない
+        * @throws InvalidMidiDataException {@link Sequencer#setSequence(Sequence)} を参照
         */
        public boolean loadNext(int offset) {
                int loadedIndex = indexOfSequenceOnSequencer();
                int index = (loadedIndex < 0 ? 0 : loadedIndex + offset);
                if( index < 0 || index >= sequenceList.size() ) return false;
-               loadToSequencer(index);
+               try {
+                       loadToSequencer(index);
+               } catch (InvalidMidiDataException ex) {
+                       ex.printStackTrace();
+                       JOptionPane.showMessageDialog(
+                               null, ex.getMessage(),
+                               ChordHelperApplet.VersionInfo.NAME, JOptionPane.ERROR_MESSAGE);
+                       return false;
+               }
                return true;
        }
 }