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;
13 import camidion.chordhelper.midieditor.MidiSequenceEditor;
16 * すべてのMIDIデバイスモデル {@link MidiTransceiverListModel} を収容するリストです。
17 * {@link MidiDeviceTreeModel} もこのリストを参照します。
19 public class MidiTransceiverListModelList extends Vector<MidiTransceiverListModel> {
21 public String toString() { return "MIDI devices"; }
23 public MidiSequenceEditor editorDialog;
25 private MidiSequencerModel sequencerModel;
26 public MidiSequencerModel getSequencerModel() { return sequencerModel; }
28 public MidiTransceiverListModelList(List<VirtualMidiDevice> guiVirtualDeviceList) {
30 // GUI仮想MIDIデバイスリストの構築
31 MidiTransceiverListModel guiModels[] = new MidiTransceiverListModel[guiVirtualDeviceList.size()];
32 for( int i=0; i<guiVirtualDeviceList.size(); i++ ) {
33 addElement(guiModels[i] = new MidiTransceiverListModel(guiVirtualDeviceList.get(i), this));
38 sequencer = MidiSystem.getSequencer(false);
39 addElement(sequencerModel = new MidiSequencerModel(sequencer, this));
40 } catch( MidiUnavailableException e ) {
41 System.out.println(ChordHelperApplet.VersionInfo.NAME +" : MIDI sequencer unavailable");
45 editorDialog = new MidiSequenceEditor(sequencerModel);
46 MidiTransceiverListModel editorDialogModel;
47 addElement(editorDialogModel = new MidiTransceiverListModel(editorDialog.getVirtualMidiDevice(), this));
48 MidiTransceiverListModel synthModel = null;
49 MidiTransceiverListModel firstMidiInModel = null;
50 MidiTransceiverListModel firstMidiOutModel = null;
51 MidiDevice.Info[] deviceInfos = MidiSystem.getMidiDeviceInfo();
52 for( MidiDevice.Info info : deviceInfos ) {
56 device = MidiSystem.getMidiDevice(info);
57 } catch( MidiUnavailableException e ) {
58 e.printStackTrace(); continue;
60 // シーケンサはすでに取得済みなのでスキップ
61 if( device instanceof Sequencer ) continue;
64 if( device instanceof Synthesizer ) {
66 addElement(synthModel = new MidiTransceiverListModel(MidiSystem.getSynthesizer(), this));
67 } catch( MidiUnavailableException e ) {
68 System.out.println(ChordHelperApplet.VersionInfo.NAME +
69 " : Java internal MIDI synthesizer unavailable");
75 MidiTransceiverListModel m;
76 addElement(m = new MidiTransceiverListModel(device, this));
77 if( m.rxSupported() && firstMidiOutModel == null ) firstMidiOutModel = m;
78 if( m.txSupported() && firstMidiInModel == null ) firstMidiInModel = m;
81 // NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
83 // そうすれば、後から開いた MIDI IN Tx デバイスからの
84 // タイムスタンプのほうが「若く」なる。これにより、
85 // 先に開かれ「少し歳を食った」Rx デバイスは
86 // 「信号が遅れてやってきた」と認識するので、
87 // 遅れを取り戻そうとして即座に音を出してくれる。
89 // 開く順序が逆になると「進みすぎるから遅らせよう」として
90 // 無用なレイテンシーが発生する原因になる。
92 MidiTransceiverListModel openModels[] = {
99 for( MidiTransceiverListModel m : openModels ) if( m != null ) {
100 m.getMidiDevice().open();
103 for( MidiTransceiverListModel m : guiModels ) {
104 m.getMidiDevice().open();
107 } catch( MidiUnavailableException ex ) {
108 ex.printStackTrace();
112 for( MidiTransceiverListModel mtx : guiModels ) {
113 for( MidiTransceiverListModel mrx : guiModels ) mtx.connectToReceiverOf(mrx);
114 mtx.connectToReceiverOf(sequencerModel);
115 mtx.connectToReceiverOf(synthModel);
116 mtx.connectToReceiverOf(firstMidiOutModel);
118 if( firstMidiInModel != null ) {
119 for( MidiTransceiverListModel m : guiModels ) firstMidiInModel.connectToReceiverOf(m);
120 firstMidiInModel.connectToReceiverOf(sequencerModel);
121 firstMidiInModel.connectToReceiverOf(synthModel);
122 firstMidiInModel.connectToReceiverOf(firstMidiOutModel);
124 if( sequencerModel != null ) {
125 for( MidiTransceiverListModel m : guiModels ) sequencerModel.connectToReceiverOf(m);
126 sequencerModel.connectToReceiverOf(synthModel);
127 sequencerModel.connectToReceiverOf(firstMidiOutModel);
129 if( editorDialogModel != null ) {
130 editorDialogModel.connectToReceiverOf(synthModel);
131 editorDialogModel.connectToReceiverOf(firstMidiOutModel);