*/
public static class VersionInfo {
public static final String NAME = "MIDI Chord Helper";
- public static final String VERSION = "Ver.20160530.1";
+ public static final String VERSION = "Ver.20160604.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/";
package camidion.chordhelper.mididevice;
import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
import javax.swing.JDialog;
+import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
*/
public class MidiDeviceDialog extends JDialog {
/**
+ * MIDIデバイスダイアログを開くアクション
+ */
+ public Action openAction = new AbstractAction() {
+ {
+ putValue(NAME, "MIDI device connection");
+ putValue(SHORT_DESCRIPTION, "MIDIデバイス間の接続を編集");
+ putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.MIDI_CONNECTOR_ICON));
+ }
+ @Override
+ public void actionPerformed(ActionEvent event) { setVisible(true); }
+ };
+ /**
* MIDIデバイスダイアログを構築します。
* @param deviceModelList デバイスモデル(MIDIコネクタリストモデル)のリスト
*/
- public MidiDeviceDialog(MidiTransceiverListModelList deviceModelList) {
+ public MidiDeviceDialog(final MidiTransceiverListModelList deviceModelList) {
setTitle(openAction.getValue(Action.NAME).toString());
setBounds( 300, 300, 800, 500 );
MidiDeviceTreeModel deviceTreeModel = new MidiDeviceTreeModel(deviceModelList);
MidiDeviceTreeView deviceTreeView = new MidiDeviceTreeView(deviceTreeModel);
- MidiDeviceInfoPane deviceInfoPane = new MidiDeviceInfoPane();
+ final MidiDeviceInfoPane deviceInfoPane = new MidiDeviceInfoPane();
MidiOpenedDevicesView desktopPane = new MidiOpenedDevicesView(deviceTreeView, deviceInfoPane, this);
deviceTreeView.addTreeSelectionListener(deviceInfoPane);
deviceTreeView.addTreeSelectionListener(desktopPane);
+ deviceTreeView.setSelectionRow(0);
add(new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
new JSplitPane(
JSplitPane.VERTICAL_SPLIT,
new JScrollPane(deviceTreeView),
- new JScrollPane(deviceInfoPane)
+ new JPanel() {{
+ add(new JScrollPane(deviceInfoPane));
+ add(new JButton("Reset time on MIDI devices") {{
+ addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ deviceModelList.resetMicrosecondPosition();
+ }
+ });
+ }});
+ setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
+ }}
){{
setDividerLocation(260);
}},
setDividerLocation(250);
}});
}
- /**
- * MIDIデバイスダイアログを開くアクション
- */
- public Action openAction = new AbstractAction() {
- {
- putValue(NAME, "MIDI device connection");
- putValue(SHORT_DESCRIPTION, "MIDIデバイス間の接続を編集");
- putValue(LARGE_ICON_KEY, new ButtonIcon(ButtonIcon.MIDI_CONNECTOR_ICON));
- }
- @Override
- public void actionPerformed(ActionEvent event) { setVisible(true); }
- };
}
return this;
}
});
- // 初期状態でツリーノードを開いた状態にする
+ // ツリーノードを開き、ルートを選択した状態にする
for( int row = 0; row < getRowCount() ; row++ ) expandRow(row);
//
// ツリーノードのToolTipを有効化
ToolTipManager.sharedInstance().registerComponent(this);
+
}
}
import camidion.chordhelper.ButtonIcon;
import camidion.chordhelper.midieditor.SequenceTickIndex;
import camidion.chordhelper.midieditor.SequenceTrackListTableModel;
+import camidion.chordhelper.midieditor.SequencerSpeedSlider;
/**
* MIDIシーケンサモデル
addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
- int val = getValue();
- getSequencer().setTempoFactor((float)(
- val == 0 ? 1.0 : Math.pow( 2.0, ((double)val)/12.0 )
- ));
+ getSequencer().setTempoFactor(SequencerSpeedSlider.tempoFactorOf(getValue()));
}
});
}};
/**
* シーケンサに合わせてミリ秒位置を更新するタイマー
*/
- private javax.swing.Timer timeRangeUpdater = new javax.swing.Timer(
- 20,
+ private javax.swing.Timer timeRangeUpdater = new javax.swing.Timer( 20,
new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
timeRangeUpdater.start();
SequenceTrackListTableModel sequenceTableModel = getSequenceTrackListTableModel();
if( sequenceTableModel != null && sequenceTableModel.hasRecordChannel() ) {
- for(MidiTransceiverListModel m : deviceModelList) m.resetMicrosecondPosition();
+ deviceModelList.resetMicrosecondPosition();
System.gc();
sequencer.startRecording();
}
if( sequenceTableModel != null || getSequencer().isOpen() ) {
getSequencer().setSequence(sequenceTableModel == null ? null : sequenceTableModel.getSequence());
}
- if( this.sequenceTableModel != null ) {
- this.sequenceTableModel.fireTableDataChanged();
- }
- if( sequenceTableModel != null ) {
- sequenceTableModel.fireTableDataChanged();
- }
+ if( this.sequenceTableModel != null ) this.sequenceTableModel.fireTableDataChanged();
+ if( sequenceTableModel != null ) sequenceTableModel.fireTableDataChanged();
this.sequenceTableModel = sequenceTableModel;
fireStateChanged();
}
if( ! txSupported() || device instanceof Sequencer ) return;
//
// デバイスを閉じる前に接続相手の情報を保存
- List<Transmitter> txList = device.getTransmitters();
+ List<Transmitter> myTxList = device.getTransmitters();
List<Receiver> peerRxList = new Vector<Receiver>();
- for( Transmitter tx : txList ) {
- Receiver rx = tx.getReceiver();
- if( rx != null ) peerRxList.add(rx);
+ Receiver rx;
+ for( Transmitter tx : myTxList ) {
+ if( (rx = tx.getReceiver()) != null ) peerRxList.add(rx);
}
List<Transmitter> peerTxList = null;
- Receiver rx = null;
if( rxSupported() ) {
rx = device.getReceivers().get(0);
peerTxList = new Vector<Transmitter>();
sequencerModel.connectToReceiverOf(firstMidiOutModel);
}
}
-}
\ No newline at end of file
+ /**
+ * すべてのデバイスについて、{@link MidiTransceiverListModel#resetMicrosecondPosition()}
+ * でマイクロ秒位置をリセットします。
+ */
+ public void resetMicrosecondPosition() {
+ for(MidiTransceiverListModel m : this) m.resetMicrosecondPosition();
+ }
+}
package camidion.chordhelper.midieditor;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import javax.swing.AbstractSpinnerModel;
import javax.swing.BoundedRangeModel;
import javax.swing.BoxLayout;
-import javax.swing.JComboBox;
+import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
+import javax.swing.JSpinner;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
/**
* シーケンサーの再生スピード調整スライダビュー
*/
public class SequencerSpeedSlider extends JPanel {
- private static final String items[] = {
- "x 1.0",
- "x 1.5",
- "x 2",
- "x 4",
- "x 8",
- "x 16",
- };
+ public static float tempoFactorOf(int val) {
+ return (float) Math.pow( 2, ((double)val)/12.0 );
+ }
+ private static final List<Hashtable<Integer,JComponent>> labeltables = new ArrayList<Hashtable<Integer,JComponent>>() {{
+ for( int i = 0; i < 5; i++ ) {
+ Hashtable<Integer,JComponent> e = new Hashtable<>();
+ add(e);
+ e.put(-i * 12, new JLabel( "x" + Double.toString(Math.pow( 2, (double)(-i) )) ));
+ e.put(0, new JLabel( "x1.0" ));
+ e.put(i * 12, new JLabel( "x" + Double.toString(Math.pow( 2, (double)i )) ));
+ }
+ }};
private JLabel titleLabel;
private JSlider slider;
public SequencerSpeedSlider(BoundedRangeModel model) {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
- add(titleLabel = new JLabel("Speed:"));
+ add(titleLabel = new JLabel("Speed: "));
add(slider = new JSlider(model){{
setPaintTicks(true);
setMajorTickSpacing(12);
setMinorTickSpacing(1);
+ setPaintLabels(true);
setVisible(false);
}});
- add(new JComboBox<String>(items) {{
- addActionListener(new ActionListener() {
+ add(new JLabel("x"));
+ add(new JSpinner(new AbstractSpinnerModel() {
+ private int index = 0;
+ @Override
+ public Object getValue() { return Math.pow( 2, (double)index ); }
+ @Override
+ public void setValue(Object value) {
+ index = (int) Math.round( Math.log((Double)value) / Math.log(2) );
+ fireStateChanged();
+ }
+ @Override
+ public Object getNextValue() {
+ return index >= 4 ? null : Math.pow( 2, (double)(++index) );
+ }
+ @Override
+ public Object getPreviousValue() {
+ return index <= 0 ? null : Math.pow( 2, (double)(--index) );
+ }
+ }) {{
+ addChangeListener(new ChangeListener() {
@Override
- public void actionPerformed(ActionEvent e) {
- int index = getSelectedIndex();
+ public void stateChanged(ChangeEvent e) {
+ int index = (int) Math.round( Math.log((Double)getValue()) / Math.log(2) );
BoundedRangeModel model = slider.getModel();
if( index == 0 ) {
model.setValue(0);
slider.setVisible(false);
titleLabel.setVisible(true);
+ return;
}
- else {
- int maxValue = ( index == 1 ? 7 : (index-1)*12 );
- model.setMinimum(-maxValue);
- model.setMaximum(maxValue);
- slider.setMajorTickSpacing( index == 1 ? 7 : 12 );
- slider.setMinorTickSpacing( index > 3 ? 12 : 1 );
- slider.setVisible(true);
- titleLabel.setVisible(false);
- }
+ int maxValue = index * 12;
+ model.setMinimum(-maxValue);
+ model.setMaximum(maxValue);
+ slider.setMajorTickSpacing(12);
+ slider.setMinorTickSpacing(index > 2 ? 12 : 1);
+ slider.setLabelTable(labeltables.get(index));
+ slider.setVisible(true);
+ titleLabel.setVisible(false);
}
});
}});