1 package camidion.chordhelper.mididevice;
4 import java.util.Vector;
6 import javax.sound.midi.MidiDevice;
7 import javax.sound.midi.MidiUnavailableException;
8 import javax.sound.midi.Receiver;
9 import javax.sound.midi.Sequencer;
10 import javax.sound.midi.Transmitter;
11 import javax.swing.AbstractListModel;
14 * {@link Transmitter} のリストを表す {@link javax.swing.ListModel}
16 public class TransmitterListModel extends AbstractListModel<Transmitter> {
17 protected MidiDeviceModel deviceModel;
18 public TransmitterListModel(MidiDeviceModel deviceModel) { this.deviceModel = deviceModel; }
19 private Transmitter dummyTx = new DummyTransmitter();
21 public Transmitter getElementAt(int index) {
22 List<Transmitter> txList = deviceModel.getMidiDevice().getTransmitters();
23 int length = txList.size();
24 if( index == length ) return dummyTx;
25 if( index > length || index < 0 ) return null;
26 return txList.get(index);
29 public int getSize() {
30 return deviceModel.getMidiDevice().getTransmitters().size() + 1;
32 public int indexOf(Object element) {
33 List<Transmitter> txList = deviceModel.getMidiDevice().getTransmitters();
34 return dummyTx.equals(element) ? txList.size() : txList.indexOf(element);
37 * 新しい{@link Transmitter}を{@link MidiDevice#getTransmitter}で生成し、
38 * このモデルを参照しているビューに通知します。
40 * @return 未接続の{@link Transmitter}
41 * @throws MidiUnavailableException リソースの制約のためにトランスミッタを使用できない場合にスローされる
43 public Transmitter openTransmitter() throws MidiUnavailableException {
44 Transmitter tx = deviceModel.getMidiDevice().getTransmitter();
45 fireIntervalAdded(this, 0, getSize());
49 * 相手のMIDIデバイスが持つ最初の{@link Receiver}を、
50 * このリストモデルの新規{@link Transmitter}に接続します。
52 * @param anotherDeviceModel 接続相手のMIDIデバイス
53 * @throws MidiUnavailableException リソースの制約のためにトランスミッタを使用できない場合にスローされる
55 public void connectToFirstReceiverOfDevice(MidiDeviceModel anotherDeviceModel) throws MidiUnavailableException {
56 List<Receiver> rxList = anotherDeviceModel.getMidiDevice().getReceivers();
57 if( rxList.isEmpty() ) return;
58 deviceModel.getTransmitterListModel().openTransmitter().setReceiver(rxList.get(0));
61 * 指定の{@link Transmitter}を閉じ、要素が減ったことを、
62 * このモデルを参照しているビューに通知します。
64 * @param tx このリストモデルで開いている{@link Transmitter}
66 public void closeTransmitter(Transmitter tx) {
68 fireIntervalRemoved(this, 0, getSize());
71 * このリストモデルにある{@link Transmitter}のうち、
72 * 引数で指定された{@link Receiver}へデータを送信しているものを全て閉じます。
73 * 閉じるとリストから自動的に削除されるので、表示の更新も行います。
75 public void closePeerTransmitterOf(Receiver rx) {
76 List<Transmitter> closingTxList = new Vector<Transmitter>();
77 List<Transmitter> txList = deviceModel.getMidiDevice().getTransmitters();
78 for( Transmitter tx : txList ) if( tx.getReceiver() == rx ) closingTxList.add(tx);
79 if( closingTxList.isEmpty() ) return;
80 int length = getSize();
81 for( Transmitter tx : closingTxList ) tx.close();
82 fireIntervalRemoved(this, 0, length);
86 * <p>マイクロ秒位置はMIDIデバイスを開いてからの時間で表されます。
87 * このメソッドではMIDIデバイスをいったん閉じて再び開くことによって
89 * 接続相手のデバイスがあった場合、元通りに接続を復元します。
91 * <p>MIDIデバイスからリアルタイムレコーディングを開始するときは、
92 * 必ずマイクロ秒位置をリセットする必要があります。
93 * (リセットされていないマイクロ秒位置がそのままシーケンサに記録されると、
94 * 大幅に後ろのほうにずれて記録されてしまいます)
97 public void resetMicrosecondPosition() {
98 MidiDevice device = deviceModel.getMidiDevice();
100 // シーケンサはこのメソッドでのリセット対象外
101 if( device instanceof Sequencer ) return;
104 List<Receiver> peerRxList = new Vector<Receiver>();
105 List<Transmitter> txList = device.getTransmitters();
106 for( Transmitter tx : txList ) {
107 Receiver rx = tx.getReceiver();
108 if( rx != null ) peerRxList.add(rx);
110 List<Transmitter> peerTxList = new Vector<Transmitter>();
111 MidiDeviceModelList deviceModelList = deviceModel.getDeviceModelList();
112 List<Receiver> rxList = device.getReceivers();
113 for( Receiver rx : rxList ) {
114 for( MidiDeviceModel m : deviceModelList ) {
115 if( m == deviceModel ) continue;
116 List<Transmitter> peerSourceTxList = m.getMidiDevice().getTransmitters();
117 for( Transmitter tx : peerSourceTxList ) if( tx.getReceiver() == rx ) peerTxList.add(tx);
120 // いったん閉じて開く(ここでマイクロ秒位置がリセットされる)
125 for( Receiver peerRx : peerRxList ) openTransmitter().setReceiver(peerRx);
126 if( ! rxList.isEmpty() ) {
127 Receiver rx = rxList.get(0);
128 for( Transmitter peerTx : peerTxList ) peerTx.setReceiver(rx);
130 } catch( MidiUnavailableException e ) {