OSDN Git Service

リファクタリング
authorAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sat, 22 Jul 2017 15:52:26 +0000 (00:52 +0900)
committerAkiyoshi Kamide <kamide@yk.rim.or.jp>
Sat, 22 Jul 2017 15:52:26 +0000 (00:52 +0900)
src/camidion/chordhelper/ChordHelperApplet.java
src/camidion/chordhelper/SongTitleLabel.java [new file with mode: 0644]
src/camidion/chordhelper/mididevice/MidiDeviceTreeModel.java
src/camidion/chordhelper/midieditor/NewSequenceDialog.java
src/camidion/chordhelper/midieditor/TempoSelecter.java
src/camidion/chordhelper/midieditor/TimeSignatureSelecter.java
src/camidion/chordhelper/music/AbstractTrackSpec.java

index fa306f3..7fe130d 100644 (file)
@@ -27,7 +27,6 @@ import javax.swing.ImageIcon;
 import javax.swing.JApplet;
 import javax.swing.JButton;
 import javax.swing.JComponent;
-import javax.swing.JLabel;
 import javax.swing.JLayeredPane;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
@@ -267,14 +266,15 @@ public class ChordHelperApplet extends JApplet {
         * @param isDark ダークモードのときtrue、明るい表示のときfalse(デフォルト)
         */
        public void setDarkMode(boolean isDark) {
-               darkModeToggleButton.setSelected(isDark);
+               if( darkModeToggleButton.isSelected() != isDark )
+                       darkModeToggleButton.doClick();
        }
        /**
         * バージョン情報
         */
        public static class VersionInfo {
                public static final String NAME = "MIDI Chord Helper";
-               public static final String VERSION = "Ver.20170523.1";
+               public static final String VERSION = "Ver.20170722.1";
                public static final String COPYRIGHT = "Copyright (C) 2004-2017";
                public static final String AUTHER = "@きよし - Akiyoshi Kamide";
                public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
@@ -297,9 +297,6 @@ public class ChordHelperApplet extends JApplet {
        private ChordMatrix chordMatrix;
        private JPanel keyboardSequencerPanel;
        private JPanel chordGuide;
-       private Color rootPaneDefaultBgcolor;
-       private Color lyricDisplayDefaultBgcolor;
-       private Border lyricDisplayDefaultBorder;
        private JSplitPane mainSplitPane;
        private JSplitPane keyboardSplitPane;
        private ChordButtonLabel enterButtonLabel;
@@ -329,7 +326,7 @@ public class ChordHelperApplet extends JApplet {
                AboutMessagePane about = new AboutMessagePane(imageIcon);
                //
                // 背景色の取得
-               rootPaneDefaultBgcolor = getContentPane().getBackground();
+               Color rootPaneDefaultBgcolor = getContentPane().getBackground();
                //
                // コードダイアグラム、コードボタン、ピアノ鍵盤、およびそれらの仮想MIDIデバイスを生成
                CapoComboBoxModel capoComboBoxModel = new CapoComboBoxModel();
@@ -342,9 +339,11 @@ public class ChordHelperApplet extends JApplet {
                        }
                        {
                                addChordMatrixListener(new ChordMatrixListener(){
+                                       @Override
                                        public void keySignatureChanged() {
                                                keyboardPanel.setCapoKey(getKeySignatureCapo());
                                        }
+                                       @Override
                                        public void chordChanged() { chordOn(); }
                                });
                                capoSelecter.checkbox.addItemListener(e->clearChord());
@@ -392,8 +391,8 @@ public class ChordHelperApplet extends JApplet {
                (lyricDisplay = new ChordTextField(sequencerModel)).addActionListener(
                        e->chordMatrix.setSelectedChord(e.getActionCommand().trim().split("[ \t\r\n]")[0])
                );
-               lyricDisplayDefaultBorder = lyricDisplay.getBorder();
-               lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();
+               Border lyricDisplayDefaultBorder = lyricDisplay.getBorder();
+               Color lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();
                //
                // メタイベント(テンポ・拍子・調号)を受信して表示するリスナーを登録
                TempoSelecter tempoSelecter = new TempoSelecter() {{ setEditable(false); }};
@@ -412,41 +411,28 @@ public class ChordHelperApplet extends JApplet {
                        }
                });
                // 再生時間位置の移動、シーケンス名の変更、またはシーケンスの入れ替えが発生したときに呼び出されるリスナーを登録
-               JLabel songTitleLabel = new JLabel();
+               SongTitleLabel songTitleLabel = new SongTitleLabel();
                sequencerModel.addChangeListener(e->{
                        Sequencer sequencer = sequencerModel.getSequencer();
                        chordMatrix.setPlaying(sequencer.isRunning());
                        SequenceTrackListTableModel sequenceModel = sequencerModel.getSequenceTrackListTableModel();
                        if( sequenceModel == null ) {
-                               songTitleLabel.setText("<html>[No MIDI file loaded]</html>");
+                               songTitleLabel.clear();
                                timesigSelecter.clear();
                                tempoSelecter.clear();
                                keysigLabel.clear();
                                return;
                        }
-                       String songTitle = sequenceModel.toString();
                        int songIndex = playlistModel.getSequenceModelList().indexOf(sequenceModel);
-                       songTitleLabel.setText("<html>"+("MIDI file " + songIndex + ": " + (
-                               songTitle.isEmpty() ? "[Untitled]" : "<font color=maroon>"+songTitle+"</font>"
-                       ))+"</html>");
+                       songTitleLabel.setSongTitle(songIndex, sequenceModel);
                        SequenceTickIndex tickIndex = sequenceModel.getSequenceTickIndex();
                        long tickPosition = sequencer.getTickPosition();
                        tickIndex.tickToMeasure(tickPosition);
                        chordMatrix.setBeat(tickIndex);
                        if( sequencerModel.getValueIsAdjusting() || ! (sequencer.isRunning() || sequencer.isRecording()) ) {
-                               MetaMessage msg;
-                               msg = tickIndex.lastMetaMessageAt(
-                                       SequenceTickIndex.MetaMessageType.TIME_SIGNATURE, tickPosition
-                               );
-                               timesigSelecter.setValue(msg==null ? null : msg.getData());
-                               msg = tickIndex.lastMetaMessageAt(
-                                       SequenceTickIndex.MetaMessageType.TEMPO, tickPosition
-                               );
-                               tempoSelecter.setTempo(msg==null ? null : msg.getData());
-                               msg = tickIndex.lastMetaMessageAt(
-                                       SequenceTickIndex.MetaMessageType.KEY_SIGNATURE, tickPosition
-                               );
-                               if(msg == null) keysigLabel.clear(); else setKeySignature(new Key(msg.getData()));
+                               timesigSelecter.setValueAt(tickIndex, tickPosition);
+                               tempoSelecter.setTempoAt(tickIndex, tickPosition);
+                               setKeySignatureAt(tickIndex, tickPosition);
                        }
                });
                sequencerModel.fireStateChanged();
@@ -461,10 +447,8 @@ public class ChordHelperApplet extends JApplet {
                                addMouseListener(new MouseAdapter() {
                                        public void mousePressed(MouseEvent event) {
                                                boolean rightClicked = (event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0;
-                                               if( rightClicked )
-                                                       chordMatrix.setSelectedChord((Chord)null);
-                                               else
-                                                       chordMatrix.setSelectedChord(lyricDisplay.getText());
+                                               String selectedChord = rightClicked ? lyricDisplay.getText() : null;
+                                               chordMatrix.setSelectedChord(selectedChord);
                                        }
                                });
                        }});
@@ -473,7 +457,28 @@ public class ChordHelperApplet extends JApplet {
                        add( Box.createHorizontalStrut(5) );
                        add( darkModeToggleButton = new JToggleButton(new ButtonIcon(ButtonIcon.DARK_MODE_ICON)) {{
                                setMargin(ZERO_INSETS);
-                               addItemListener(e->innerSetDarkMode(darkModeToggleButton.isSelected()));
+                               addItemListener(e->{
+                                       boolean isDark = darkModeToggleButton.isSelected();
+                                       Color col = isDark ? Color.black : null;
+                                       getContentPane().setBackground(isDark ? Color.black : rootPaneDefaultBgcolor);
+                                       mainSplitPane.setBackground(col);
+                                       keyboardSplitPane.setBackground(col);
+                                       enterButtonLabel.setDarkMode(isDark);
+                                       chordGuide.setBackground(col);
+                                       lyricDisplay.setBorder(isDark ? null : lyricDisplayDefaultBorder);
+                                       lyricDisplay.setBackground(isDark ?
+                                               chordMatrix.darkModeColorset.backgrounds[2] :
+                                               lyricDisplayDefaultBgcolor
+                                       );
+                                       lyricDisplay.setForeground(isDark ? Color.white : null);
+                                       inversionOmissionButton.setBackground(col);
+                                       anoGakkiToggleButton.setBackground(col);
+                                       keyboardSequencerPanel.setBackground(col);
+                                       chordDiagram.setBackground(col);
+                                       chordDiagram.titleLabel.setDarkMode(isDark);
+                                       chordMatrix.setDarkMode(isDark);
+                                       keyboardPanel.setDarkMode(isDark);
+                               });
                                setToolTipText("Light / Dark - 明かりを点灯/消灯");
                                setBorder(null);
                        }});
@@ -583,32 +588,17 @@ public class ChordHelperApplet extends JApplet {
        @Override
        public void stop() { sequencerModel.stop(); }
 
-       private void innerSetDarkMode(boolean isDark) {
-               Color col = isDark ? Color.black : null;
-               getContentPane().setBackground(isDark ? Color.black : rootPaneDefaultBgcolor);
-               mainSplitPane.setBackground(col);
-               keyboardSplitPane.setBackground(col);
-               enterButtonLabel.setDarkMode(isDark);
-               chordGuide.setBackground(col);
-               lyricDisplay.setBorder(isDark ? null : lyricDisplayDefaultBorder);
-               lyricDisplay.setBackground(isDark ?
-                       chordMatrix.darkModeColorset.backgrounds[2] :
-                       lyricDisplayDefaultBgcolor
-               );
-               lyricDisplay.setForeground(isDark ? Color.white : null);
-               inversionOmissionButton.setBackground(col);
-               anoGakkiToggleButton.setBackground(col);
-               keyboardSequencerPanel.setBackground(col);
-               chordDiagram.setBackground(col);
-               chordDiagram.titleLabel.setDarkMode(isDark);
-               chordMatrix.setDarkMode(isDark);
-               keyboardPanel.setDarkMode(isDark);
-       }
-
        private void setKeySignature(Key key) {
                keysigLabel.setKey(key);
                chordMatrix.setKeySignature(key);
        }
+       private void setKeySignatureAt(SequenceTickIndex tickIndex, long tickPosition) {
+               MetaMessage msg = tickIndex.lastMetaMessageAt(
+                       SequenceTickIndex.MetaMessageType.KEY_SIGNATURE,
+                       tickPosition
+               );
+               if(msg == null) keysigLabel.clear(); else setKeySignature(new Key(msg.getData()));
+       }
 
        private int[] chordOnNotes = null;
        /**
diff --git a/src/camidion/chordhelper/SongTitleLabel.java b/src/camidion/chordhelper/SongTitleLabel.java
new file mode 100644 (file)
index 0000000..a8da089
--- /dev/null
@@ -0,0 +1,16 @@
+package camidion.chordhelper;
+
+import javax.swing.JLabel;
+
+import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
+
+public class SongTitleLabel extends JLabel {
+       public void clear() {
+               setText("<html>[No MIDI file loaded]</html>");
+       }
+       public void setSongTitle(int songIndex, SequenceTrackListTableModel sequenceModel) {
+               String title = sequenceModel.toString();
+               String titleHtml = title.isEmpty()?"[Untitled]":"<font color=maroon>"+title+"</font>";
+               setText("<html>MIDI file " + songIndex + ": " + titleHtml + "</html>");
+       }
+}
index 11a7018..22fb7af 100644 (file)
@@ -1,6 +1,5 @@
 package camidion.chordhelper.mididevice;
 
-import java.util.AbstractCollection;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -8,7 +7,6 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Vector;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -38,6 +36,7 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
        public String toString() { return "MIDI devices"; }
 
        protected List<MidiDeviceModel> deviceModelList = new ArrayList<>();
+
        @Override
        public int size() { return deviceModelList.size(); }
        @Override
@@ -45,42 +44,21 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
 
        protected Map<MidiDeviceInOutType, List<MidiDeviceModel>> deviceModelTree
                = MidiDeviceInOutType.stream().collect(Collectors.toMap(Function.identity(), t-> new ArrayList<>()));
-       /**
-        * {@link AbstractList#add(E)}の操作を内部的に行います。
-        * 指定された要素をこのリストの最後に追加し、ツリー構造にも反映します。
-        * @param dm 追加するMIDIデバイスモデル
-        * @return true({@link AbstractList#add(E)} と同様)
-        */
-       protected boolean addInternally(MidiDeviceModel dm) {
-               if( ! deviceModelList.add(dm) ) return false;
-               deviceModelTree.get(dm.getInOutType()).add(dm);
-               return true;
-       }
+
        protected MidiDeviceModel add(MidiDevice device) {
                if( device == null ) return null;
-               MidiDeviceModel m = new MidiDeviceModel(device,this);
-               addInternally(m);
-               return m;
+               MidiDeviceModel dm;
+               if( device instanceof Sequencer ) {
+                       dm = new MidiSequencerModel((Sequencer)device,this);
+               } else {
+                       dm = new MidiDeviceModel(device,this);
+               }
+               deviceModelList.add(dm);
+               deviceModelTree.get(dm.getInOutType()).add(dm);
+               return dm;
        }
        protected MidiSequencerModel add(Sequencer sequencer) {
-               if( sequencer == null ) return null;
-               MidiSequencerModel m = new MidiSequencerModel(sequencer,this);
-               addInternally(m);
-               return m;
-       }
-       /**
-        * {@link AbstractCollection#removeAll(Collection)}の操作を内部的に行います。
-        * 指定されたコレクションに該当するすべての要素を、このリストから削除します。
-        * このリストが変更された場合、ツリー構造にも反映されます。
-        * @param c 削除する要素のコレクション
-        * @return このリストが変更された場合はtrue({@link AbstractCollection#removeAll(Collection)} と同様)
-        */
-       protected boolean removeAllInternally(Collection<?> c) {
-               if( ! deviceModelList.removeAll(c) ) return false;
-               c.stream().filter(o -> o instanceof MidiDeviceModel).forEach(
-                       o -> deviceModelTree.get(((MidiDeviceModel)o).getInOutType()).remove(o)
-               );
-               return true;
+               return (MidiSequencerModel)add((MidiDevice)sequencer);
        }
        @Override
        public Object getRoot() { return this; }
@@ -217,8 +195,8 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                        //   NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
                        //
                        //   そうすれば、後から開いた MIDI IN Tx デバイスからのタイムスタンプのほうが「若く」なるので、
-                       //   相手の MIDI OUT Rx デバイスは「信号が遅れてやってきた」と認識、遅れを取り戻そうとして
-                       //   即座に音を出してくれる。
+                       //   相手の MIDI OUT Rx デバイスは「若いころの信号が遅れてやってきた」と認識、
+                       //        遅れを取り戻そうとして即座に音を出してくれる。
                        //
                        //   開く順序が逆になると「進みすぎるから遅らせよう」として無用なレイテンシーが発生する原因になる。
                        synthModel, firstMidiOutModel,  // MIDI OUT Rx
@@ -230,12 +208,12 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
                // 自身のTx/Rx同士の接続は、シーケンサーモデルはなし、それ以外(GUIデバイスモデル)はあり。
                connectDevices(
                        openedDeviceModels.stream().filter(
-                               m->Objects.nonNull(m.getReceiverListModel())
+                               rxm->Objects.nonNull(rxm.getReceiverListModel())
                        ).collect(Collectors.toMap(
                                Function.identity(),
-                               r->openedDeviceModels.stream()
-                               .filter(m->Objects.nonNull(m.getTransmitterListModel()))
-                               .filter(t-> !(t == sequencerModel && t == r))
+                               rxm->openedDeviceModels.stream()
+                               .filter(txm->Objects.nonNull(txm.getTransmitterListModel()))
+                               .filter(txm-> !(txm == sequencerModel && txm == rxm))
                                .collect(Collectors.toList())
                        ))
                );
@@ -275,10 +253,11 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         * </ul>
         */
        private void connectDevices(Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections) {
-               rxToTxConnections.keySet().stream().forEach(rxm->{
+               rxToTxConnections.entrySet().stream().forEach(rxe->{
+                       MidiDeviceModel rxm = rxe.getKey();
                        Receiver rx = rxm.getReceiver();
                        if( rx == null ) return;
-                       rxToTxConnections.get(rxm).stream().filter(Objects::nonNull).forEach(txm->{
+                       rxe.getValue().stream().filter(Objects::nonNull).forEach(txm->{
                                try {
                                        txm.getTransmitterListModel().openTransmitter().setReceiver(rx);
                                } catch( Exception ex ) {
@@ -296,29 +275,30 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
         * 新しく装着されたMIDIデバイスを開くことができるようになります。
         * 同時に、取り外されたMIDIデバイスが閉じられ、そのデバイスの表示も消えます。
         * </p>
-        * <p>別のMIDIデバイスに
+        * <p>USB端子からMIDIデバイスを抜いた場合、そのMIDIデバイスの
         * {@link Transmitter} や {@link Receiver}
-        * を接続したままUSB端子からMIDIデバイスを抜くと、
-        * {@link MidiSystem#getMidiDeviceInfo()} ã\82\92å\91¼ã\81³å\87ºã\81\97ã\81\9fã\81¨ã\81\8dã\81« Java VM ã\81\8cã\82¯ã\83©ã\83\83ã\82·ã\83¥ã\81\97ã\81¦ã\81\97ã\81¾ã\81\86ã\81\9fã\82\81ã\80\81
-        * 最初に{@link #disconnectAllDevices()}で接続をすべて切断してから
+        * を接続したまま
+        * {@link MidiSystem#getMidiDeviceInfo()} ã\82\92å\91¼ã\81³å\87ºã\81\99ã\81¨ Java VM ã\81\8cã\82¯ã\83©ã\83\83ã\82·ã\83¥ã\81\97ã\81¦ã\81\97ã\81¾ã\81\84ã\81¾ã\81\99ã\80\82
+        * これを避けるため、最初に{@link #disconnectAllDevices()}で接続をすべて切断してから
         * MIDIデバイスリストを最新の状態に更新し、その後{@link #connectDevices(Map)}で接続を復元します。
         * </p>
         */
        public void update() {
-               Map<MidiDeviceModel, Collection<MidiDeviceModel>> savedConnections = disconnectAllDevices();
-               List<MidiDevice.Info> additionalInfo = new Vector<>(getMidiDeviceInfo());
-               List<MidiDeviceModel> closedModels = stream().filter(model->{
+               Map<MidiDeviceModel, Collection<MidiDeviceModel>> saved = disconnectAllDevices();
+               List<MidiDevice.Info> newDeviceInfo = new ArrayList<>(getMidiDeviceInfo());
+               Collection<MidiDeviceModel> oldDeviceModels = stream().filter(model->{
                        MidiDevice device = model.getMidiDevice();
                        if( device instanceof VirtualMidiDevice ) return false;
-                       if( additionalInfo.remove(device.getDeviceInfo()) ) return false;
+                       if( newDeviceInfo.remove(device.getDeviceInfo()) ) return false;
                        device.close(); return true;
-               }).collect(Collectors.toList());
-               if( removeAllInternally(closedModels) ) {
-                       savedConnections.keySet().removeAll(closedModels); // Rx
-                       savedConnections.values().forEach(m->m.removeAll(closedModels)); // Tx
+               }).collect(Collectors.toSet());
+               if( deviceModelList.removeAll(oldDeviceModels) ) {
+                       oldDeviceModels.forEach(m->deviceModelTree.get(m.getInOutType()).remove(m));
+                       saved.keySet().removeAll(oldDeviceModels); // Rx
+                       saved.values().forEach(m->m.removeAll(oldDeviceModels)); // Tx
                }
-               additionalInfo.forEach(info->add(getMidiDevice(info)));
-               connectDevices(savedConnections);
+               newDeviceInfo.forEach(info->add(getMidiDevice(info)));
+               connectDevices(saved);
                fireTreeStructureChanged(this, null, null, null);
        }
 
index fa1878b..356bc89 100644 (file)
@@ -31,6 +31,7 @@ import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
 import javax.swing.JSpinner;
 import javax.swing.JTabbedPane;
 import javax.swing.JTextArea;
@@ -144,12 +145,13 @@ public class NewSequenceDialog extends JDialog {
                                        add(ppqComboBox);
                                        add(measureSelecter);
                                }});
-                               add(new JButton("Randomize (Tempo, Time signature, Chord progression)") {{
-                                       setMargin(ChordHelperApplet.ZERO_INSETS);
-                                       addActionListener(e->setRandomChordProgression(measureSelecter.getMeasureDuration()));
-                               }});
+                               add(new JSeparator());
                                add(new JPanel() {{
                                        setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
+                                       add(new JButton("Randomize") {{
+                                               setMargin(ChordHelperApplet.ZERO_INSETS);
+                                               addActionListener(e->setRandomChordProgression(measureSelecter.getMeasureDuration()));
+                                       }});
                                        add(tempoSelecter);
                                        add(new JPanel() {{
                                                add(new JLabel("Time signature ="));
index 8bb4bf0..8c786b2 100644 (file)
@@ -4,6 +4,7 @@ import java.awt.Component;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 
+import javax.sound.midi.MetaMessage;
 import javax.swing.Box;
 import javax.swing.BoxLayout;
 import javax.swing.JLabel;
@@ -115,5 +116,17 @@ public class TempoSelecter extends JPanel {
        public void setTempo(byte msgdata[]) {
                if( msgdata==null ) clear(); else setTempo(MIDISpec.byteArrayToQpmTempo(msgdata));
        }
+       /**
+        * MIDIシーケンスの特定tick位置におけるテンポを設定します。
+        * @param tickIndex MIDIシーケンスのtickインデックス
+        * @param tickPosition tick位置
+        */
+       public void setTempoAt(SequenceTickIndex tickIndex, long tickPosition) {
+               MetaMessage msg = tickIndex.lastMetaMessageAt(
+                       SequenceTickIndex.MetaMessageType.TEMPO,
+                       tickPosition
+               );
+               setTempo(msg==null ? null : msg.getData());
+       }
        public void clear() { setTempo(DEFAULT_QPM); }
 }
index f5a24e9..3a4e650 100644 (file)
@@ -1,5 +1,6 @@
 package camidion.chordhelper.midieditor;
 
+import javax.sound.midi.MetaMessage;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
@@ -57,6 +58,13 @@ public class TimeSignatureSelecter extends JPanel {
        public void setValue(byte[] data) {
                if(data == null) clear(); else setValue(data[0], data[1]);
        }
+       public void setValueAt(SequenceTickIndex tickIndex, long tickPosition) {
+               MetaMessage msg = tickIndex.lastMetaMessageAt(
+                       SequenceTickIndex.MetaMessageType.TIME_SIGNATURE,
+                       tickPosition
+               );
+               setValue(msg==null ? null : msg.getData());
+       }
        private boolean editable;
        public boolean isEditable() { return editable; }
        public void setEditable(boolean editable) {
index 685e664..70ac7f9 100644 (file)
@@ -13,8 +13,6 @@ import javax.sound.midi.Track;
  * MIDIトラックの仕様を表すクラス
  */
 public abstract class AbstractTrackSpec {
-       public static final int BEAT_RESOLUTION = 2;
-       // 最短の音符の長さ(四分音符を何回半分にするか)
        public String name = null;
        Track track = null;
        FirstTrackSpec firstTrackSpec = null;