• R/O
  • HTTP
  • SSH
  • HTTPS

MIDIChordHelper: Commit

Javaアプリ MIDI Chord Helper のソースコード


Commit MetaInfo

Revision2aacd0e8c3dc2ad7c3ef3276fef26e91cd080a13 (tree)
Time2017-07-23 00:52:26
AuthorAkiyoshi Kamide <kamide@yk.r...>
CommiterAkiyoshi Kamide

Log Message

リファクタリング

Change Summary

Incremental Difference

--- a/src/camidion/chordhelper/ChordHelperApplet.java
+++ b/src/camidion/chordhelper/ChordHelperApplet.java
@@ -27,7 +27,6 @@ import javax.swing.ImageIcon;
2727 import javax.swing.JApplet;
2828 import javax.swing.JButton;
2929 import javax.swing.JComponent;
30-import javax.swing.JLabel;
3130 import javax.swing.JLayeredPane;
3231 import javax.swing.JOptionPane;
3332 import javax.swing.JPanel;
@@ -267,14 +266,15 @@ public class ChordHelperApplet extends JApplet {
267266 * @param isDark ダークモードのときtrue、明るい表示のときfalse(デフォルト)
268267 */
269268 public void setDarkMode(boolean isDark) {
270- darkModeToggleButton.setSelected(isDark);
269+ if( darkModeToggleButton.isSelected() != isDark )
270+ darkModeToggleButton.doClick();
271271 }
272272 /**
273273 * バージョン情報
274274 */
275275 public static class VersionInfo {
276276 public static final String NAME = "MIDI Chord Helper";
277- public static final String VERSION = "Ver.20170523.1";
277+ public static final String VERSION = "Ver.20170722.1";
278278 public static final String COPYRIGHT = "Copyright (C) 2004-2017";
279279 public static final String AUTHER = "@きよし - Akiyoshi Kamide";
280280 public static final String URL = "http://www.yk.rim.or.jp/~kamide/music/chordhelper/";
@@ -297,9 +297,6 @@ public class ChordHelperApplet extends JApplet {
297297 private ChordMatrix chordMatrix;
298298 private JPanel keyboardSequencerPanel;
299299 private JPanel chordGuide;
300- private Color rootPaneDefaultBgcolor;
301- private Color lyricDisplayDefaultBgcolor;
302- private Border lyricDisplayDefaultBorder;
303300 private JSplitPane mainSplitPane;
304301 private JSplitPane keyboardSplitPane;
305302 private ChordButtonLabel enterButtonLabel;
@@ -329,7 +326,7 @@ public class ChordHelperApplet extends JApplet {
329326 AboutMessagePane about = new AboutMessagePane(imageIcon);
330327 //
331328 // 背景色の取得
332- rootPaneDefaultBgcolor = getContentPane().getBackground();
329+ Color rootPaneDefaultBgcolor = getContentPane().getBackground();
333330 //
334331 // コードダイアグラム、コードボタン、ピアノ鍵盤、およびそれらの仮想MIDIデバイスを生成
335332 CapoComboBoxModel capoComboBoxModel = new CapoComboBoxModel();
@@ -342,9 +339,11 @@ public class ChordHelperApplet extends JApplet {
342339 }
343340 {
344341 addChordMatrixListener(new ChordMatrixListener(){
342+ @Override
345343 public void keySignatureChanged() {
346344 keyboardPanel.setCapoKey(getKeySignatureCapo());
347345 }
346+ @Override
348347 public void chordChanged() { chordOn(); }
349348 });
350349 capoSelecter.checkbox.addItemListener(e->clearChord());
@@ -392,8 +391,8 @@ public class ChordHelperApplet extends JApplet {
392391 (lyricDisplay = new ChordTextField(sequencerModel)).addActionListener(
393392 e->chordMatrix.setSelectedChord(e.getActionCommand().trim().split("[ \t\r\n]")[0])
394393 );
395- lyricDisplayDefaultBorder = lyricDisplay.getBorder();
396- lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();
394+ Border lyricDisplayDefaultBorder = lyricDisplay.getBorder();
395+ Color lyricDisplayDefaultBgcolor = lyricDisplay.getBackground();
397396 //
398397 // メタイベント(テンポ・拍子・調号)を受信して表示するリスナーを登録
399398 TempoSelecter tempoSelecter = new TempoSelecter() {{ setEditable(false); }};
@@ -412,41 +411,28 @@ public class ChordHelperApplet extends JApplet {
412411 }
413412 });
414413 // 再生時間位置の移動、シーケンス名の変更、またはシーケンスの入れ替えが発生したときに呼び出されるリスナーを登録
415- JLabel songTitleLabel = new JLabel();
414+ SongTitleLabel songTitleLabel = new SongTitleLabel();
416415 sequencerModel.addChangeListener(e->{
417416 Sequencer sequencer = sequencerModel.getSequencer();
418417 chordMatrix.setPlaying(sequencer.isRunning());
419418 SequenceTrackListTableModel sequenceModel = sequencerModel.getSequenceTrackListTableModel();
420419 if( sequenceModel == null ) {
421- songTitleLabel.setText("<html>[No MIDI file loaded]</html>");
420+ songTitleLabel.clear();
422421 timesigSelecter.clear();
423422 tempoSelecter.clear();
424423 keysigLabel.clear();
425424 return;
426425 }
427- String songTitle = sequenceModel.toString();
428426 int songIndex = playlistModel.getSequenceModelList().indexOf(sequenceModel);
429- songTitleLabel.setText("<html>"+("MIDI file " + songIndex + ": " + (
430- songTitle.isEmpty() ? "[Untitled]" : "<font color=maroon>"+songTitle+"</font>"
431- ))+"</html>");
427+ songTitleLabel.setSongTitle(songIndex, sequenceModel);
432428 SequenceTickIndex tickIndex = sequenceModel.getSequenceTickIndex();
433429 long tickPosition = sequencer.getTickPosition();
434430 tickIndex.tickToMeasure(tickPosition);
435431 chordMatrix.setBeat(tickIndex);
436432 if( sequencerModel.getValueIsAdjusting() || ! (sequencer.isRunning() || sequencer.isRecording()) ) {
437- MetaMessage msg;
438- msg = tickIndex.lastMetaMessageAt(
439- SequenceTickIndex.MetaMessageType.TIME_SIGNATURE, tickPosition
440- );
441- timesigSelecter.setValue(msg==null ? null : msg.getData());
442- msg = tickIndex.lastMetaMessageAt(
443- SequenceTickIndex.MetaMessageType.TEMPO, tickPosition
444- );
445- tempoSelecter.setTempo(msg==null ? null : msg.getData());
446- msg = tickIndex.lastMetaMessageAt(
447- SequenceTickIndex.MetaMessageType.KEY_SIGNATURE, tickPosition
448- );
449- if(msg == null) keysigLabel.clear(); else setKeySignature(new Key(msg.getData()));
433+ timesigSelecter.setValueAt(tickIndex, tickPosition);
434+ tempoSelecter.setTempoAt(tickIndex, tickPosition);
435+ setKeySignatureAt(tickIndex, tickPosition);
450436 }
451437 });
452438 sequencerModel.fireStateChanged();
@@ -461,10 +447,8 @@ public class ChordHelperApplet extends JApplet {
461447 addMouseListener(new MouseAdapter() {
462448 public void mousePressed(MouseEvent event) {
463449 boolean rightClicked = (event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0;
464- if( rightClicked )
465- chordMatrix.setSelectedChord((Chord)null);
466- else
467- chordMatrix.setSelectedChord(lyricDisplay.getText());
450+ String selectedChord = rightClicked ? lyricDisplay.getText() : null;
451+ chordMatrix.setSelectedChord(selectedChord);
468452 }
469453 });
470454 }});
@@ -473,7 +457,28 @@ public class ChordHelperApplet extends JApplet {
473457 add( Box.createHorizontalStrut(5) );
474458 add( darkModeToggleButton = new JToggleButton(new ButtonIcon(ButtonIcon.DARK_MODE_ICON)) {{
475459 setMargin(ZERO_INSETS);
476- addItemListener(e->innerSetDarkMode(darkModeToggleButton.isSelected()));
460+ addItemListener(e->{
461+ boolean isDark = darkModeToggleButton.isSelected();
462+ Color col = isDark ? Color.black : null;
463+ getContentPane().setBackground(isDark ? Color.black : rootPaneDefaultBgcolor);
464+ mainSplitPane.setBackground(col);
465+ keyboardSplitPane.setBackground(col);
466+ enterButtonLabel.setDarkMode(isDark);
467+ chordGuide.setBackground(col);
468+ lyricDisplay.setBorder(isDark ? null : lyricDisplayDefaultBorder);
469+ lyricDisplay.setBackground(isDark ?
470+ chordMatrix.darkModeColorset.backgrounds[2] :
471+ lyricDisplayDefaultBgcolor
472+ );
473+ lyricDisplay.setForeground(isDark ? Color.white : null);
474+ inversionOmissionButton.setBackground(col);
475+ anoGakkiToggleButton.setBackground(col);
476+ keyboardSequencerPanel.setBackground(col);
477+ chordDiagram.setBackground(col);
478+ chordDiagram.titleLabel.setDarkMode(isDark);
479+ chordMatrix.setDarkMode(isDark);
480+ keyboardPanel.setDarkMode(isDark);
481+ });
477482 setToolTipText("Light / Dark - 明かりを点灯/消灯");
478483 setBorder(null);
479484 }});
@@ -583,32 +588,17 @@ public class ChordHelperApplet extends JApplet {
583588 @Override
584589 public void stop() { sequencerModel.stop(); }
585590
586- private void innerSetDarkMode(boolean isDark) {
587- Color col = isDark ? Color.black : null;
588- getContentPane().setBackground(isDark ? Color.black : rootPaneDefaultBgcolor);
589- mainSplitPane.setBackground(col);
590- keyboardSplitPane.setBackground(col);
591- enterButtonLabel.setDarkMode(isDark);
592- chordGuide.setBackground(col);
593- lyricDisplay.setBorder(isDark ? null : lyricDisplayDefaultBorder);
594- lyricDisplay.setBackground(isDark ?
595- chordMatrix.darkModeColorset.backgrounds[2] :
596- lyricDisplayDefaultBgcolor
597- );
598- lyricDisplay.setForeground(isDark ? Color.white : null);
599- inversionOmissionButton.setBackground(col);
600- anoGakkiToggleButton.setBackground(col);
601- keyboardSequencerPanel.setBackground(col);
602- chordDiagram.setBackground(col);
603- chordDiagram.titleLabel.setDarkMode(isDark);
604- chordMatrix.setDarkMode(isDark);
605- keyboardPanel.setDarkMode(isDark);
606- }
607-
608591 private void setKeySignature(Key key) {
609592 keysigLabel.setKey(key);
610593 chordMatrix.setKeySignature(key);
611594 }
595+ private void setKeySignatureAt(SequenceTickIndex tickIndex, long tickPosition) {
596+ MetaMessage msg = tickIndex.lastMetaMessageAt(
597+ SequenceTickIndex.MetaMessageType.KEY_SIGNATURE,
598+ tickPosition
599+ );
600+ if(msg == null) keysigLabel.clear(); else setKeySignature(new Key(msg.getData()));
601+ }
612602
613603 private int[] chordOnNotes = null;
614604 /**
--- /dev/null
+++ b/src/camidion/chordhelper/SongTitleLabel.java
@@ -0,0 +1,16 @@
1+package camidion.chordhelper;
2+
3+import javax.swing.JLabel;
4+
5+import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
6+
7+public class SongTitleLabel extends JLabel {
8+ public void clear() {
9+ setText("<html>[No MIDI file loaded]</html>");
10+ }
11+ public void setSongTitle(int songIndex, SequenceTrackListTableModel sequenceModel) {
12+ String title = sequenceModel.toString();
13+ String titleHtml = title.isEmpty()?"[Untitled]":"<font color=maroon>"+title+"</font>";
14+ setText("<html>MIDI file " + songIndex + ": " + titleHtml + "</html>");
15+ }
16+}
--- a/src/camidion/chordhelper/mididevice/MidiDeviceTreeModel.java
+++ b/src/camidion/chordhelper/mididevice/MidiDeviceTreeModel.java
@@ -1,6 +1,5 @@
11 package camidion.chordhelper.mididevice;
22
3-import java.util.AbstractCollection;
43 import java.util.AbstractList;
54 import java.util.ArrayList;
65 import java.util.Arrays;
@@ -8,7 +7,6 @@ import java.util.Collection;
87 import java.util.List;
98 import java.util.Map;
109 import java.util.Objects;
11-import java.util.Vector;
1210 import java.util.function.Function;
1311 import java.util.stream.Collectors;
1412 import java.util.stream.Stream;
@@ -38,6 +36,7 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
3836 public String toString() { return "MIDI devices"; }
3937
4038 protected List<MidiDeviceModel> deviceModelList = new ArrayList<>();
39+
4140 @Override
4241 public int size() { return deviceModelList.size(); }
4342 @Override
@@ -45,42 +44,21 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
4544
4645 protected Map<MidiDeviceInOutType, List<MidiDeviceModel>> deviceModelTree
4746 = MidiDeviceInOutType.stream().collect(Collectors.toMap(Function.identity(), t-> new ArrayList<>()));
48- /**
49- * {@link AbstractList#add(E)}の操作を内部的に行います。
50- * 指定された要素をこのリストの最後に追加し、ツリー構造にも反映します。
51- * @param dm 追加するMIDIデバイスモデル
52- * @return true({@link AbstractList#add(E)} と同様)
53- */
54- protected boolean addInternally(MidiDeviceModel dm) {
55- if( ! deviceModelList.add(dm) ) return false;
56- deviceModelTree.get(dm.getInOutType()).add(dm);
57- return true;
58- }
47+
5948 protected MidiDeviceModel add(MidiDevice device) {
6049 if( device == null ) return null;
61- MidiDeviceModel m = new MidiDeviceModel(device,this);
62- addInternally(m);
63- return m;
50+ MidiDeviceModel dm;
51+ if( device instanceof Sequencer ) {
52+ dm = new MidiSequencerModel((Sequencer)device,this);
53+ } else {
54+ dm = new MidiDeviceModel(device,this);
55+ }
56+ deviceModelList.add(dm);
57+ deviceModelTree.get(dm.getInOutType()).add(dm);
58+ return dm;
6459 }
6560 protected MidiSequencerModel add(Sequencer sequencer) {
66- if( sequencer == null ) return null;
67- MidiSequencerModel m = new MidiSequencerModel(sequencer,this);
68- addInternally(m);
69- return m;
70- }
71- /**
72- * {@link AbstractCollection#removeAll(Collection)}の操作を内部的に行います。
73- * 指定されたコレクションに該当するすべての要素を、このリストから削除します。
74- * このリストが変更された場合、ツリー構造にも反映されます。
75- * @param c 削除する要素のコレクション
76- * @return このリストが変更された場合はtrue({@link AbstractCollection#removeAll(Collection)} と同様)
77- */
78- protected boolean removeAllInternally(Collection<?> c) {
79- if( ! deviceModelList.removeAll(c) ) return false;
80- c.stream().filter(o -> o instanceof MidiDeviceModel).forEach(
81- o -> deviceModelTree.get(((MidiDeviceModel)o).getInOutType()).remove(o)
82- );
83- return true;
61+ return (MidiSequencerModel)add((MidiDevice)sequencer);
8462 }
8563 @Override
8664 public Object getRoot() { return this; }
@@ -217,8 +195,8 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
217195 // NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
218196 //
219197 // そうすれば、後から開いた MIDI IN Tx デバイスからのタイムスタンプのほうが「若く」なるので、
220- // 相手の MIDI OUT Rx デバイスは「信号が遅れてやってきた」と認識、遅れを取り戻そうとして
221- // 即座に音を出してくれる。
198+ // 相手の MIDI OUT Rx デバイスは「若いころの信号が遅れてやってきた」と認識、
199+ // 遅れを取り戻そうとして即座に音を出してくれる。
222200 //
223201 // 開く順序が逆になると「進みすぎるから遅らせよう」として無用なレイテンシーが発生する原因になる。
224202 synthModel, firstMidiOutModel, // MIDI OUT Rx
@@ -230,12 +208,12 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
230208 // 自身のTx/Rx同士の接続は、シーケンサーモデルはなし、それ以外(GUIデバイスモデル)はあり。
231209 connectDevices(
232210 openedDeviceModels.stream().filter(
233- m->Objects.nonNull(m.getReceiverListModel())
211+ rxm->Objects.nonNull(rxm.getReceiverListModel())
234212 ).collect(Collectors.toMap(
235213 Function.identity(),
236- r->openedDeviceModels.stream()
237- .filter(m->Objects.nonNull(m.getTransmitterListModel()))
238- .filter(t-> !(t == sequencerModel && t == r))
214+ rxm->openedDeviceModels.stream()
215+ .filter(txm->Objects.nonNull(txm.getTransmitterListModel()))
216+ .filter(txm-> !(txm == sequencerModel && txm == rxm))
239217 .collect(Collectors.toList())
240218 ))
241219 );
@@ -275,10 +253,11 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
275253 * </ul>
276254 */
277255 private void connectDevices(Map<MidiDeviceModel, Collection<MidiDeviceModel>> rxToTxConnections) {
278- rxToTxConnections.keySet().stream().forEach(rxm->{
256+ rxToTxConnections.entrySet().stream().forEach(rxe->{
257+ MidiDeviceModel rxm = rxe.getKey();
279258 Receiver rx = rxm.getReceiver();
280259 if( rx == null ) return;
281- rxToTxConnections.get(rxm).stream().filter(Objects::nonNull).forEach(txm->{
260+ rxe.getValue().stream().filter(Objects::nonNull).forEach(txm->{
282261 try {
283262 txm.getTransmitterListModel().openTransmitter().setReceiver(rx);
284263 } catch( Exception ex ) {
@@ -296,29 +275,30 @@ public class MidiDeviceTreeModel extends AbstractList<MidiDeviceModel> implement
296275 * 新しく装着されたMIDIデバイスを開くことができるようになります。
297276 * 同時に、取り外されたMIDIデバイスが閉じられ、そのデバイスの表示も消えます。
298277 * </p>
299- * <p>別のMIDIデバイスに
278+ * <p>USB端子からMIDIデバイスを抜いた場合、そのMIDIデバイスの
300279 * {@link Transmitter} や {@link Receiver}
301- * を接続したままUSB端子からMIDIデバイスを抜くと、
302- * {@link MidiSystem#getMidiDeviceInfo()} を呼び出したときに Java VM がクラッシュしてしまうため、
303- * 最初に{@link #disconnectAllDevices()}で接続をすべて切断してから
280+ * を接続したままで
281+ * {@link MidiSystem#getMidiDeviceInfo()} を呼び出すと Java VM がクラッシュしてしまいます。
282+ * これを避けるため、最初に{@link #disconnectAllDevices()}で接続をすべて切断してから
304283 * MIDIデバイスリストを最新の状態に更新し、その後{@link #connectDevices(Map)}で接続を復元します。
305284 * </p>
306285 */
307286 public void update() {
308- Map<MidiDeviceModel, Collection<MidiDeviceModel>> savedConnections = disconnectAllDevices();
309- List<MidiDevice.Info> additionalInfo = new Vector<>(getMidiDeviceInfo());
310- List<MidiDeviceModel> closedModels = stream().filter(model->{
287+ Map<MidiDeviceModel, Collection<MidiDeviceModel>> saved = disconnectAllDevices();
288+ List<MidiDevice.Info> newDeviceInfo = new ArrayList<>(getMidiDeviceInfo());
289+ Collection<MidiDeviceModel> oldDeviceModels = stream().filter(model->{
311290 MidiDevice device = model.getMidiDevice();
312291 if( device instanceof VirtualMidiDevice ) return false;
313- if( additionalInfo.remove(device.getDeviceInfo()) ) return false;
292+ if( newDeviceInfo.remove(device.getDeviceInfo()) ) return false;
314293 device.close(); return true;
315- }).collect(Collectors.toList());
316- if( removeAllInternally(closedModels) ) {
317- savedConnections.keySet().removeAll(closedModels); // Rx
318- savedConnections.values().forEach(m->m.removeAll(closedModels)); // Tx
294+ }).collect(Collectors.toSet());
295+ if( deviceModelList.removeAll(oldDeviceModels) ) {
296+ oldDeviceModels.forEach(m->deviceModelTree.get(m.getInOutType()).remove(m));
297+ saved.keySet().removeAll(oldDeviceModels); // Rx
298+ saved.values().forEach(m->m.removeAll(oldDeviceModels)); // Tx
319299 }
320- additionalInfo.forEach(info->add(getMidiDevice(info)));
321- connectDevices(savedConnections);
300+ newDeviceInfo.forEach(info->add(getMidiDevice(info)));
301+ connectDevices(saved);
322302 fireTreeStructureChanged(this, null, null, null);
323303 }
324304
--- a/src/camidion/chordhelper/midieditor/NewSequenceDialog.java
+++ b/src/camidion/chordhelper/midieditor/NewSequenceDialog.java
@@ -31,6 +31,7 @@ import javax.swing.JLabel;
3131 import javax.swing.JOptionPane;
3232 import javax.swing.JPanel;
3333 import javax.swing.JScrollPane;
34+import javax.swing.JSeparator;
3435 import javax.swing.JSpinner;
3536 import javax.swing.JTabbedPane;
3637 import javax.swing.JTextArea;
@@ -144,12 +145,13 @@ public class NewSequenceDialog extends JDialog {
144145 add(ppqComboBox);
145146 add(measureSelecter);
146147 }});
147- add(new JButton("Randomize (Tempo, Time signature, Chord progression)") {{
148- setMargin(ChordHelperApplet.ZERO_INSETS);
149- addActionListener(e->setRandomChordProgression(measureSelecter.getMeasureDuration()));
150- }});
148+ add(new JSeparator());
151149 add(new JPanel() {{
152150 setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
151+ add(new JButton("Randomize") {{
152+ setMargin(ChordHelperApplet.ZERO_INSETS);
153+ addActionListener(e->setRandomChordProgression(measureSelecter.getMeasureDuration()));
154+ }});
153155 add(tempoSelecter);
154156 add(new JPanel() {{
155157 add(new JLabel("Time signature ="));
--- a/src/camidion/chordhelper/midieditor/TempoSelecter.java
+++ b/src/camidion/chordhelper/midieditor/TempoSelecter.java
@@ -4,6 +4,7 @@ import java.awt.Component;
44 import java.awt.event.MouseAdapter;
55 import java.awt.event.MouseEvent;
66
7+import javax.sound.midi.MetaMessage;
78 import javax.swing.Box;
89 import javax.swing.BoxLayout;
910 import javax.swing.JLabel;
@@ -115,5 +116,17 @@ public class TempoSelecter extends JPanel {
115116 public void setTempo(byte msgdata[]) {
116117 if( msgdata==null ) clear(); else setTempo(MIDISpec.byteArrayToQpmTempo(msgdata));
117118 }
119+ /**
120+ * MIDIシーケンスの特定tick位置におけるテンポを設定します。
121+ * @param tickIndex MIDIシーケンスのtickインデックス
122+ * @param tickPosition tick位置
123+ */
124+ public void setTempoAt(SequenceTickIndex tickIndex, long tickPosition) {
125+ MetaMessage msg = tickIndex.lastMetaMessageAt(
126+ SequenceTickIndex.MetaMessageType.TEMPO,
127+ tickPosition
128+ );
129+ setTempo(msg==null ? null : msg.getData());
130+ }
118131 public void clear() { setTempo(DEFAULT_QPM); }
119132 }
--- a/src/camidion/chordhelper/midieditor/TimeSignatureSelecter.java
+++ b/src/camidion/chordhelper/midieditor/TimeSignatureSelecter.java
@@ -1,5 +1,6 @@
11 package camidion.chordhelper.midieditor;
22
3+import javax.sound.midi.MetaMessage;
34 import javax.swing.JComboBox;
45 import javax.swing.JLabel;
56 import javax.swing.JPanel;
@@ -57,6 +58,13 @@ public class TimeSignatureSelecter extends JPanel {
5758 public void setValue(byte[] data) {
5859 if(data == null) clear(); else setValue(data[0], data[1]);
5960 }
61+ public void setValueAt(SequenceTickIndex tickIndex, long tickPosition) {
62+ MetaMessage msg = tickIndex.lastMetaMessageAt(
63+ SequenceTickIndex.MetaMessageType.TIME_SIGNATURE,
64+ tickPosition
65+ );
66+ setValue(msg==null ? null : msg.getData());
67+ }
6068 private boolean editable;
6169 public boolean isEditable() { return editable; }
6270 public void setEditable(boolean editable) {
--- a/src/camidion/chordhelper/music/AbstractTrackSpec.java
+++ b/src/camidion/chordhelper/music/AbstractTrackSpec.java
@@ -13,8 +13,6 @@ import javax.sound.midi.Track;
1313 * MIDIトラックの仕様を表すクラス
1414 */
1515 public abstract class AbstractTrackSpec {
16- public static final int BEAT_RESOLUTION = 2;
17- // 最短の音符の長さ(四分音符を何回半分にするか)
1816 public String name = null;
1917 Track track = null;
2018 FirstTrackSpec firstTrackSpec = null;
Show on old repository browser