1 package camidion.chordhelper.midieditor;
\r
3 import java.awt.Component;
\r
4 import java.awt.event.MouseEvent;
\r
5 import java.awt.event.MouseListener;
\r
7 import javax.sound.midi.MetaEventListener;
\r
8 import javax.sound.midi.MetaMessage;
\r
9 import javax.swing.Box;
\r
10 import javax.swing.BoxLayout;
\r
11 import javax.swing.JLabel;
\r
12 import javax.swing.JPanel;
\r
13 import javax.swing.JSpinner;
\r
14 import javax.swing.SpinnerNumberModel;
\r
15 import javax.swing.SwingUtilities;
\r
17 import camidion.chordhelper.ButtonIcon;
\r
18 import camidion.chordhelper.music.MIDISpec;
\r
21 * テンポ選択(QPM: Quarter Per Minute)
\r
23 public class TempoSelecter extends JPanel implements MouseListener, MetaEventListener {
\r
24 static final int DEFAULT_QPM = 120;
\r
25 protected SpinnerNumberModel tempoSpinnerModel =
\r
26 new SpinnerNumberModel(DEFAULT_QPM, 1, 999, 1);
\r
27 private JLabel tempoLabel = new JLabel(
\r
28 "=", new ButtonIcon(ButtonIcon.QUARTER_NOTE_ICON), JLabel.CENTER
\r
30 setVerticalAlignment(JLabel.CENTER);
\r
32 private JLabel tempoValueLabel = new JLabel(""+DEFAULT_QPM);
\r
33 private JSpinner tempoSpinner = new JSpinner(tempoSpinnerModel);
\r
34 public TempoSelecter() {
\r
35 String tooltip = "Tempo in quatrers per minute - テンポ(1分あたりの四分音符の数)";
\r
36 tempoSpinner.setToolTipText(tooltip);
\r
37 tempoValueLabel.setToolTipText(tooltip);
\r
38 setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
\r
40 add(Box.createHorizontalStrut(5));
\r
42 add(tempoValueLabel);
\r
44 tempoLabel.addMouseListener(this);
\r
46 private long prevBeatMicrosecondPosition = 0;
\r
47 private class SetTempoRunnable implements Runnable {
\r
49 public SetTempoRunnable(byte[] qpm) { this.qpm = qpm; }
\r
51 public void run() { setTempo(qpm);}
\r
54 public void meta(MetaMessage msg) {
\r
55 switch(msg.getType()) {
\r
56 case 0x51: // Tempo (3 bytes) - テンポ
\r
57 if( ! SwingUtilities.isEventDispatchThread() ) {
\r
58 SwingUtilities.invokeLater(new SetTempoRunnable(msg.getData()));
\r
61 setTempo(msg.getData());
\r
66 public void mousePressed(MouseEvent e) {
\r
67 Component obj = e.getComponent();
\r
68 if(obj == tempoLabel && isEditable()) {
\r
70 // Adjust tempo by interval time between two clicks
\r
72 long currentMicrosecond = System.nanoTime()/1000;
\r
73 // midi_ch_selecter.noteOn( 9, 37, 100 );
\r
74 long interval_us = currentMicrosecond - prevBeatMicrosecondPosition;
\r
75 prevBeatMicrosecondPosition = currentMicrosecond;
\r
76 if( interval_us < 2000000L /* Shorter than 2 sec only */ ) {
\r
77 int tempo_in_bpm = (int)(240000000L / interval_us) >> 2; // n/4拍子の場合のみを想定
\r
78 int old_tempo_in_bpm = getTempoInQpm();
\r
79 setTempo( ( tempo_in_bpm + old_tempo_in_bpm * 2 ) / 3 );
\r
83 public void mouseReleased(MouseEvent e) { }
\r
84 public void mouseEntered(MouseEvent e) { }
\r
85 public void mouseExited(MouseEvent e) { }
\r
86 public void mouseClicked(MouseEvent e) { }
\r
87 private boolean editable;
\r
90 * @return 編集可能ならtrue
\r
92 public boolean isEditable() { return editable; }
\r
95 * @param editable 編集可能ならtrue
\r
97 public void setEditable( boolean editable ) {
\r
98 this.editable = editable;
\r
99 tempoSpinner.setVisible( editable );
\r
100 tempoValueLabel.setVisible( !editable );
\r
102 // Copy spinner's value to label
\r
103 tempoValueLabel.setText(
\r
104 ""+tempoSpinnerModel.getNumber().intValue()
\r
107 tempoLabel.setToolTipText(
\r
109 "Click rhythmically to adjust tempo - ここをクリックしてリズムをとるとテンポを合わせられます"
\r
115 * @return テンポ [BPM](QPM)
\r
117 public int getTempoInQpm() {
\r
118 return tempoSpinnerModel.getNumber().intValue();
\r
121 * テンポをMIDIメタメッセージのバイト列として返します。
\r
122 * @return MIDIメタメッセージのバイト列
\r
124 public byte[] getTempoByteArray() {
\r
125 return MIDISpec.qpmTempoToByteArray(getTempoInQpm());
\r
129 * @param qpm BPM(QPM)の値
\r
131 public void setTempo(int qpm) {
\r
132 tempoSpinnerModel.setValue(new Integer(qpm));
\r
133 tempoValueLabel.setText(""+qpm);
\r
136 * MIDIメタメッセージのバイト列からテンポを設定します。
\r
137 * @param msgdata MIDIメタメッセージのバイト列(null を指定した場合はデフォルトに戻る)
\r
139 public void setTempo(byte msgdata[]) {
\r
140 setTempo(msgdata==null ? DEFAULT_QPM: MIDISpec.byteArrayToQpmTempo(msgdata));
\r