OSDN Git Service

同期モードの選択をMIDI Editorに追加
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Tue, 10 Dec 2013 16:45:07 +0000 (16:45 +0000)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Tue, 10 Dec 2013 16:45:07 +0000 (16:45 +0000)
git-svn-id: https://svn.sourceforge.jp/svnroot/midichordhelper/MIDIChordHelper@28 302f1594-2db2-43b1-aaa4-6307b5a2a2de

src/ChordHelperApplet.java
src/MIDIDevice.java
src/MIDIEditor.java
src/MIDISequencer.java

index aa771a5..21aad5d 100644 (file)
@@ -268,7 +268,7 @@ public class ChordHelperApplet extends JApplet {
         */\r
        public static class VersionInfo {\r
                public static final String      NAME = "MIDI Chord Helper";\r
-               public static final String      VERSION = "Ver.20131210.1";\r
+               public static final String      VERSION = "Ver.20131211.1";\r
                public static final String      COPYRIGHT = "Copyright (C) 2004-2013";\r
                public static final String      AUTHER = "@きよし - Akiyoshi Kamide";\r
                public static final String      URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";\r
index 60697dd..714de33 100644 (file)
@@ -889,10 +889,15 @@ class MidiConnecterListModel extends AbstractListModel<AutoCloseable> {
        }\r
        /**\r
         * マイクロ秒位置をリセットします。\r
-        * <p>これはMIDIデバイスからリアルタイムレコーディングを開始するタイミングで\r
-        * 必ず行う必要があります。\r
-        * (マイクロ秒位置がリセットされていないと、そのままシーケンサに記録され、\r
-        * 記録位置が大幅に後ろのほうにずれてしまいます)\r
+        * <p>マイクロ秒位置はMIDIデバイスを開いてからの時間で表されます。\r
+        * このメソッドではMIDIデバイスをいったん閉じて再び開くことによって\r
+        * 時間位置をリセットします。\r
+        * 接続相手のデバイスがあった場合、元通りに接続を復元します。\r
+        * </p>\r
+        * <p>MIDIデバイスからリアルタイムレコーディングを開始するときは、\r
+        * 必ずマイクロ秒位置をリセットする必要があります。\r
+        * (リセットされていないマイクロ秒位置がそのままシーケンサに記録されると、\r
+        * 大幅に後ろのほうにずれて記録されてしまいます)\r
         * </p>\r
         */\r
        public void resetMicrosecondPosition() {\r
@@ -924,8 +929,7 @@ class MidiConnecterListModel extends AbstractListModel<AutoCloseable> {
                                }\r
                        }\r
                }\r
-               // デバイスを一旦閉じてまた開くことにより\r
-               // マイクロ秒位置をリセットする\r
+               // いったん閉じて開く(ここでマイクロ秒位置がリセットされる)\r
                device.close();\r
                try {\r
                        device.open();\r
index fa53dfe..b873e39 100644 (file)
@@ -304,7 +304,7 @@ class MidiEditor extends JDialog implements DropTargetListener {
                        for( SequenceListTableModel.Column c : SequenceListTableModel.Column.values() ) {\r
                                TableColumn tc = colModel.getColumn(c.ordinal());\r
                                tc.setPreferredWidth(c.preferredWidth);\r
-                               if( c == SequenceListTableModel.Column.SEQ_LENGTH ) {\r
+                               if( c == SequenceListTableModel.Column.LENGTH ) {\r
                                        lengthColumn = tc;\r
                                }\r
                        }\r
@@ -317,7 +317,7 @@ class MidiEditor extends JDialog implements DropTargetListener {
                        // タイトルに合計シーケンス長を表示\r
                        if( lengthColumn != null ) {\r
                                int sec = getModel().getTotalSeconds();\r
-                               String title = SequenceListTableModel.Column.SEQ_LENGTH.title;\r
+                               String title = SequenceListTableModel.Column.LENGTH.title;\r
                                title = String.format(title+" [%02d:%02d]", sec/60, sec%60);\r
                                lengthColumn.setHeaderValue(title);\r
                        }\r
@@ -337,7 +337,7 @@ class MidiEditor extends JDialog implements DropTargetListener {
                        implements TableCellEditor\r
                {\r
                        public PositionCellEditor() {\r
-                               int column = SequenceListTableModel.Column.SEQ_POSITION.ordinal();\r
+                               int column = SequenceListTableModel.Column.POSITION.ordinal();\r
                                TableColumn tc = getColumnModel().getColumn(column);\r
                                tc.setCellEditor(this);\r
                        }\r
@@ -381,7 +381,7 @@ class MidiEditor extends JDialog implements DropTargetListener {
                        );\r
                        public PlayButtonCellEditor() {\r
                                playButton.setMargin(ZERO_INSETS);\r
-                               int column = SequenceListTableModel.Column.SEQ_PLAY.ordinal();\r
+                               int column = SequenceListTableModel.Column.PLAY.ordinal();\r
                                TableColumn tc = getColumnModel().getColumn(column);\r
                                tc.setCellRenderer(this);\r
                                tc.setCellEditor(this);\r
@@ -1221,7 +1221,7 @@ class MidiEditor extends JDialog implements DropTargetListener {
                );\r
                // レイアウト\r
                setTitle("MIDI Editor/Playlist - MIDI Chord Helper");\r
-               setBounds( 150, 200, 850, 500 );\r
+               setBounds( 150, 200, 900, 500 );\r
                setLayout(new FlowLayout());\r
                new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true);\r
                JPanel playlistPanel = new JPanel() {{\r
@@ -1239,6 +1239,12 @@ class MidiEditor extends JDialog implements DropTargetListener {
                                                setMargin(ZERO_INSETS);\r
                                        }});\r
                                }\r
+                               if(sequenceListTable.base64EncodeAction != null) {\r
+                                       add(Box.createRigidArea(new Dimension(5, 0)));\r
+                                       add(new JButton(sequenceListTable.base64EncodeAction) {{\r
+                                               setMargin(ZERO_INSETS);\r
+                                       }});\r
+                               }\r
                                add(Box.createRigidArea(new Dimension(5, 0)));\r
                                SequenceListTableModel sequenceListTableModel = sequenceListTable.getModel();\r
                                add(new JButton(sequenceListTableModel.moveToTopAction) {{\r
@@ -1248,12 +1254,6 @@ class MidiEditor extends JDialog implements DropTargetListener {
                                add(new JButton(sequenceListTableModel.moveToBottomAction) {{\r
                                        setMargin(ZERO_INSETS);\r
                                }});\r
-                               if(sequenceListTable.base64EncodeAction != null) {\r
-                                       add(Box.createRigidArea(new Dimension(5, 0)));\r
-                                       add(new JButton(sequenceListTable.base64EncodeAction) {{\r
-                                               setMargin(ZERO_INSETS);\r
-                                       }});\r
-                               }\r
                                if( sequenceListTable.midiFileChooser != null ) {\r
                                        add(Box.createRigidArea(new Dimension(5, 0)));\r
                                        add(new JButton(\r
@@ -1270,6 +1270,18 @@ class MidiEditor extends JDialog implements DropTargetListener {
                                add(new SequencerSpeedSlider(\r
                                        sequenceListTableModel.sequencerModel.speedSliderModel\r
                                ));\r
+                               add( Box.createRigidArea(new Dimension(5, 0)) );\r
+                               add(new JPanel() {{\r
+                                       add(new JLabel("SyncMode:"));\r
+                                       add(new JLabel("Master"));\r
+                                       add(new JComboBox<Sequencer.SyncMode>(\r
+                                               sequenceListTable.getModel().sequencerModel.masterSyncModeModel\r
+                                       ));\r
+                                       add(new JLabel("Slave"));\r
+                                       add(new JComboBox<Sequencer.SyncMode>(\r
+                                               sequenceListTable.getModel().sequencerModel.slaveSyncModeModel\r
+                                       ));\r
+                               }});\r
                        }};\r
                        setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));\r
                        add(new JScrollPane(sequenceListTable));\r
@@ -1354,6 +1366,7 @@ class SequencerSpeedSlider extends JPanel {
        private JLabel titleLabel;\r
        private JSlider slider;\r
        public SequencerSpeedSlider(BoundedRangeModel model) {\r
+               setLayout(new BoxLayout(this, BoxLayout.X_AXIS));\r
                add(titleLabel = new JLabel("Speed:"));\r
                add(slider = new JSlider(model){{\r
                        setPaintTicks(true);\r
@@ -1480,7 +1493,7 @@ class SequenceListTableModel extends AbstractTableModel {
                        // セルのレンダラーが描く再生ボタンには効かないようなので、\r
                        // セルを突っついて再表示させる。\r
                        int rowIndex = indexOfSequenceOnSequencer();\r
-                       int colIndex = Column.SEQ_PLAY.ordinal();\r
+                       int colIndex = Column.PLAY.ordinal();\r
                        fireTableCellUpdated(rowIndex, colIndex);\r
                }\r
        }\r
@@ -1548,7 +1561,7 @@ class SequenceListTableModel extends AbstractTableModel {
                                if(value == newValue) return;\r
                                value = newValue;\r
                                int rowIndex = indexOfSequenceOnSequencer();\r
-                               fireTableCellUpdated(rowIndex, Column.SEQ_POSITION.ordinal());\r
+                               fireTableCellUpdated(rowIndex, Column.POSITION.ordinal());\r
                        }\r
                }\r
                @Override\r
@@ -1590,14 +1603,14 @@ class SequenceListTableModel extends AbstractTableModel {
         */\r
        public enum Column {\r
                /** MIDIシーケンスの番号 */\r
-               SEQ_NUMBER("No.", Integer.class, 20),\r
+               NUMBER("No.", Integer.class, 20),\r
                /** 再生ボタン */\r
-               SEQ_PLAY("Play/Stop", String.class, 60) {\r
+               PLAY("Play/Stop", String.class, 60) {\r
                        @Override\r
                        public boolean isCellEditable() { return true; }\r
                },\r
                /** 再生中の時間位置(分:秒) */\r
-               SEQ_POSITION("Position", String.class, 60) {\r
+               POSITION("Position", String.class, 60) {\r
                        @Override\r
                        public boolean isCellEditable() { return true; } // ダブルクリックだけ有効\r
                        @Override\r
@@ -1607,7 +1620,7 @@ class SequenceListTableModel extends AbstractTableModel {
                        }\r
                },\r
                /** シーケンスの時間長(分:秒) */\r
-               SEQ_LENGTH("Length", String.class, 80) {\r
+               LENGTH("Length", String.class, 80) {\r
                        @Override\r
                        public Object getValueOf(SequenceTrackListTableModel sequenceModel) {\r
                                long usec = sequenceModel.getSequence().getMicrosecondLength();\r
@@ -1632,7 +1645,7 @@ class SequenceListTableModel extends AbstractTableModel {
                        }\r
                },\r
                /** シーケンス名(最初のトラックの名前) */\r
-               SEQ_NAME("Sequence name", String.class, 250) {\r
+               NAME("Sequence name", String.class, 250) {\r
                        @Override\r
                        public boolean isCellEditable() { return true; }\r
                        public Object getValueOf(SequenceTrackListTableModel sequenceModel) {\r
@@ -1708,7 +1721,7 @@ class SequenceListTableModel extends AbstractTableModel {
        @Override\r
        public Object getValueAt(int row, int column) {\r
                Column c = Column.values()[column];\r
-               return c == Column.SEQ_NUMBER ? row : c.getValueOf(sequenceList.get(row));\r
+               return c == Column.NUMBER ? row : c.getValueOf(sequenceList.get(row));\r
        }\r
        @Override\r
        public void setValueAt(Object val, int row, int column) {\r
@@ -1719,7 +1732,7 @@ class SequenceListTableModel extends AbstractTableModel {
                        sequenceList.get(row).setFilename((String)val);\r
                        fireTableCellUpdated(row, column);\r
                        break;\r
-               case SEQ_NAME:\r
+               case NAME:\r
                        // シーケンス名の設定または変更\r
                        if( sequenceList.get(row).setName((String)val) )\r
                                fireTableCellUpdated(row, Column.MODIFIED.ordinal());\r
@@ -1945,8 +1958,8 @@ class SequenceListTableModel extends AbstractTableModel {
                        return;\r
                sequencerModel.setSequenceTrackListTableModel(newSeq);\r
                int columnIndices[] = {\r
-                       Column.SEQ_PLAY.ordinal(),\r
-                       Column.SEQ_POSITION.ordinal(),\r
+                       Column.PLAY.ordinal(),\r
+                       Column.POSITION.ordinal(),\r
                };\r
                if( oldSeq != null ) {\r
                        int oldIndex = sequenceList.indexOf(oldSeq);\r
@@ -2376,17 +2389,46 @@ class TrackEventListTableModel extends AbstractTableModel {
         */\r
        public enum Column {\r
                /** MIDIイベント番号 */\r
-               EVENT_NUMBER("No.", Integer.class, 20),\r
+               EVENT_NUMBER("No.", Integer.class, 15) {\r
+                       @Override\r
+                       public boolean isCellEditable() { return false; }\r
+               },\r
                /** tick位置 */\r
-               TICK_POSITION("TickPos.", Long.class, 40),\r
+               TICK_POSITION("TickPos.", Long.class, 40) {\r
+                       @Override\r
+                       public Object getValue(MidiEvent event) {\r
+                               return event.getTick();\r
+                       }\r
+               },\r
                /** tick位置に対応する小節 */\r
-               MEASURE_POSITION("Measure", Integer.class, 40),\r
+               MEASURE_POSITION("Measure", Integer.class, 30) {\r
+                       public Object getValue(SequenceTickIndex sti, MidiEvent event) {\r
+                               return sti.tickToMeasure(event.getTick()) + 1;\r
+                       }\r
+               },\r
                /** tick位置に対応する拍 */\r
-               BEAT_POSITION("Beat", Integer.class, 20),\r
+               BEAT_POSITION("Beat", Integer.class, 20) {\r
+                       @Override\r
+                       public Object getValue(SequenceTickIndex sti, MidiEvent event) {\r
+                               sti.tickToMeasure(event.getTick());\r
+                               return sti.lastBeat + 1;\r
+                       }\r
+               },\r
                /** tick位置に対応する余剰tick(拍に収まらずに余ったtick数) */\r
-               EXTRA_TICK_POSITION("ExTick", Integer.class, 20),\r
+               EXTRA_TICK_POSITION("ExTick", Integer.class, 20) {\r
+                       @Override\r
+                       public Object getValue(SequenceTickIndex sti, MidiEvent event) {\r
+                               sti.tickToMeasure(event.getTick());\r
+                               return sti.lastExtraTick;\r
+                       }\r
+               },\r
                /** MIDIメッセージ */\r
-               MESSAGE("MIDI Message", String.class, 200);\r
+               MESSAGE("MIDI Message", String.class, 300) {\r
+                       @Override\r
+                       public Object getValue(MidiEvent event) {\r
+                               return msgToString(event.getMessage());\r
+                       }\r
+               };\r
                private String title;\r
                private Class<?> columnClass;\r
                int preferredWidth;\r
@@ -2402,6 +2444,25 @@ class TrackEventListTableModel extends AbstractTableModel {
                        this.columnClass = columnClass;\r
                        this.preferredWidth = preferredWidth;\r
                }\r
+               /**\r
+                * セルを編集できるときtrue、編集できないときfalseを返します。\r
+                */\r
+               public boolean isCellEditable() { return true; }\r
+               /**\r
+                * 列の値を返します。\r
+                * @param event 対象イベント\r
+                * @return この列の対象イベントにおける値\r
+                */\r
+               public Object getValue(MidiEvent event) { return ""; }\r
+               /**\r
+                * 列の値を返します。\r
+                * @param sti MIDIシーケンスデータのtickインデックス\r
+                * @param event 対象イベント\r
+                * @return この列の対象イベントにおける値\r
+                */\r
+               public Object getValue(SequenceTickIndex sti, MidiEvent event) {\r
+                       return getValue(event);\r
+               }\r
        }\r
        /**\r
         * ラップされているMIDIトラック\r
@@ -2452,19 +2513,16 @@ class TrackEventListTableModel extends AbstractTableModel {
        }\r
        @Override\r
        public Object getValueAt(int row, int column) {\r
-               switch(Column.values()[column]) {\r
-               case EVENT_NUMBER: return row;\r
-               case TICK_POSITION: return track.get(row).getTick();\r
+               Column c = Column.values()[column];\r
+               if( c == Column.EVENT_NUMBER ) return row;\r
+               MidiEvent event = track.get(row);\r
+               switch(c) {\r
                case MEASURE_POSITION:\r
-                       return sequenceTrackListTableModel.getSequenceTickIndex().tickToMeasure(track.get(row).getTick()) + 1;\r
                case BEAT_POSITION:\r
-                       sequenceTrackListTableModel.getSequenceTickIndex().tickToMeasure(track.get(row).getTick());\r
-                       return sequenceTrackListTableModel.getSequenceTickIndex().lastBeat + 1;\r
                case EXTRA_TICK_POSITION:\r
-                       sequenceTrackListTableModel.getSequenceTickIndex().tickToMeasure(track.get(row).getTick());\r
-                       return sequenceTrackListTableModel.getSequenceTickIndex().lastExtraTick;\r
-               case MESSAGE: return msgToString(track.get(row).getMessage());\r
-               default: return "";\r
+                       return c.getValue(sequenceTrackListTableModel.getSequenceTickIndex(), event);\r
+               default:\r
+                       return c.getValue(event);\r
                }\r
        }\r
        /**\r
@@ -2472,14 +2530,7 @@ class TrackEventListTableModel extends AbstractTableModel {
         */\r
        @Override\r
        public boolean isCellEditable(int row, int column) {\r
-               switch(Column.values()[column]) {\r
-               case TICK_POSITION:\r
-               case MEASURE_POSITION:\r
-               case BEAT_POSITION:\r
-               case EXTRA_TICK_POSITION:\r
-               case MESSAGE: return true;\r
-               default: return false;\r
-               }\r
+               return Column.values()[column].isCellEditable();\r
        }\r
        /**\r
         * セルの値を変更します。\r
index 0239c06..f406822 100644 (file)
@@ -13,13 +13,17 @@ import javax.swing.AbstractAction;
 import javax.swing.Action;\r
 import javax.swing.BoundedRangeModel;\r
 import javax.swing.BoxLayout;\r
+import javax.swing.ComboBoxModel;\r
 import javax.swing.DefaultBoundedRangeModel;\r
+import javax.swing.DefaultComboBoxModel;\r
 import javax.swing.Icon;\r
 import javax.swing.JLabel;\r
 import javax.swing.JPanel;\r
 import javax.swing.event.ChangeEvent;\r
 import javax.swing.event.ChangeListener;\r
 import javax.swing.event.EventListenerList;\r
+import javax.swing.event.ListDataEvent;\r
+import javax.swing.event.ListDataListener;\r
 \r
 /**\r
  * シーケンサの現在位置(分:秒)を表示するビュー\r
@@ -493,5 +497,40 @@ class MidiSequencerModel extends MidiConnecterListModel
                @Override\r
                public void actionPerformed(ActionEvent event) { moveMeasure(1); }\r
        };\r
+       /**\r
+        * マスター同期モードのコンボボックスモデル\r
+        */\r
+       public ComboBoxModel<Sequencer.SyncMode> masterSyncModeModel =\r
+               new DefaultComboBoxModel<Sequencer.SyncMode>(getSequencer().getMasterSyncModes()) {{\r
+                       addListDataListener(new ListDataListener() {\r
+                               @Override\r
+                               public void intervalAdded(ListDataEvent e) { }\r
+                               @Override\r
+                               public void intervalRemoved(ListDataEvent e) { }\r
+                               @Override\r
+                               public void contentsChanged(ListDataEvent e) {\r
+                                       getSequencer().setMasterSyncMode(\r
+                                               (Sequencer.SyncMode)getSelectedItem()\r
+                                       );\r
+                               }\r
+                       });\r
+               }};\r
+       /**\r
+        * スレーブ同期モードのコンボボックスモデル\r
+        */\r
+       public ComboBoxModel<Sequencer.SyncMode> slaveSyncModeModel =\r
+               new DefaultComboBoxModel<Sequencer.SyncMode>(getSequencer().getSlaveSyncModes()) {{\r
+                       addListDataListener(new ListDataListener() {\r
+                               @Override\r
+                               public void intervalAdded(ListDataEvent e) { }\r
+                               @Override\r
+                               public void intervalRemoved(ListDataEvent e) { }\r
+                               @Override\r
+                               public void contentsChanged(ListDataEvent e) {\r
+                                       getSequencer().setSlaveSyncMode(\r
+                                               (Sequencer.SyncMode)getSelectedItem()\r
+                                       );\r
+                               }\r
+                       });\r
+               }};\r
 }\r
-\r