1 package camidion.chordhelper.mididevice;
4 import java.util.Vector;
6 import javax.sound.midi.MidiDevice;
7 import javax.sound.midi.MidiSystem;
8 import javax.sound.midi.MidiUnavailableException;
9 import javax.sound.midi.Sequencer;
10 import javax.sound.midi.Synthesizer;
12 import camidion.chordhelper.ChordHelperApplet;
15 * 仮想MIDIデバイスを含めたすべてのMIDIデバイスモデル {@link MidiTransceiverListModel} を収容するリスト
17 public class MidiTransceiverListModelList extends Vector<MidiTransceiverListModel> {
19 public String toString() { return "MIDI devices"; }
21 private MidiSequencerModel sequencerModel;
22 public MidiSequencerModel getSequencerModel() { return sequencerModel; }
24 public MidiTransceiverListModelList(List<VirtualMidiDevice> guiVirtualDeviceList) {
27 MidiTransceiverListModel guiModels[] = new MidiTransceiverListModel[guiVirtualDeviceList.size()];
28 for( int i=0; i<guiVirtualDeviceList.size(); i++ ) {
29 addElement(guiModels[i] = new MidiTransceiverListModel(guiVirtualDeviceList.get(i), this));
34 sequencer = MidiSystem.getSequencer(false);
35 addElement(sequencerModel = new MidiSequencerModel(sequencer, this));
36 } catch( MidiUnavailableException e ) {
37 System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
41 MidiTransceiverListModel synthModel = null;
42 MidiTransceiverListModel firstMidiInModel = null;
43 MidiTransceiverListModel firstMidiOutModel = null;
44 MidiDevice.Info[] deviceInfos = MidiSystem.getMidiDeviceInfo();
45 for( MidiDevice.Info info : deviceInfos ) {
48 device = MidiSystem.getMidiDevice(info);
49 } catch( MidiUnavailableException e ) {
50 e.printStackTrace(); continue;
52 // シーケンサはすでに取得済みなのでスキップ
53 if( device instanceof Sequencer ) continue;
56 if( device instanceof Synthesizer ) {
58 addElement(synthModel = new MidiTransceiverListModel(MidiSystem.getSynthesizer(), this));
59 } catch( MidiUnavailableException e ) {
60 System.out.println(ChordHelperApplet.VersionInfo.NAME +
61 " : Java internal MIDI synthesizer unavailable");
67 MidiTransceiverListModel m;
68 addElement(m = new MidiTransceiverListModel(device, this));
69 if( m.rxSupported() && firstMidiOutModel == null ) firstMidiOutModel = m;
70 if( m.txSupported() && firstMidiInModel == null ) firstMidiInModel = m;
73 // NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
75 // そうすれば、後から開いた MIDI IN Tx デバイスからの
76 // タイムスタンプのほうが「若く」なる。これにより、
77 // 先に開かれ「少し歳を食った」Rx デバイスは
78 // 「信号が遅れてやってきた」と認識するので、
79 // 遅れを取り戻そうとして即座に音を出してくれる。
81 // 開く順序が逆になると「進みすぎるから遅らせよう」として
82 // 無用なレイテンシーが発生する原因になる。
84 MidiTransceiverListModel openModels[] = {
90 for( MidiTransceiverListModel m : openModels ) if( m != null ) {
91 m.getMidiDevice().open();
94 for( MidiTransceiverListModel m : guiModels ) {
95 m.getMidiDevice().open();
98 } catch( MidiUnavailableException ex ) {
103 for( MidiTransceiverListModel mtx : guiModels ) {
104 for( MidiTransceiverListModel mrx : guiModels ) mtx.connectToReceiverOf(mrx);
105 mtx.connectToReceiverOf(sequencerModel);
106 mtx.connectToReceiverOf(synthModel);
107 mtx.connectToReceiverOf(firstMidiOutModel);
109 if( firstMidiInModel != null ) {
110 for( MidiTransceiverListModel m : guiModels ) firstMidiInModel.connectToReceiverOf(m);
111 firstMidiInModel.connectToReceiverOf(sequencerModel);
112 firstMidiInModel.connectToReceiverOf(synthModel);
113 firstMidiInModel.connectToReceiverOf(firstMidiOutModel);
115 if( sequencerModel != null ) {
116 for( MidiTransceiverListModel m : guiModels ) sequencerModel.connectToReceiverOf(m);
117 sequencerModel.connectToReceiverOf(synthModel);
118 sequencerModel.connectToReceiverOf(firstMidiOutModel);
122 * すべてのデバイスについて、{@link MidiTransceiverListModel#resetMicrosecondPosition()}
125 public void resetMicrosecondPosition() {
126 for(MidiTransceiverListModel m : this) m.resetMicrosecondPosition();
131 public void closeAllDevices() {
132 for(MidiTransceiverListModel m : this) m.device.close();