OSDN Git Service

7c8a93dd6cbed972a6944f611b7bdf46c1b44010
[midichordhelper/MIDIChordHelper.git] / src / camidion / chordhelper / mididevice / MidiTransceiverListModelList.java
1 package camidion.chordhelper.mididevice;
2
3 import java.util.List;
4 import java.util.Vector;
5
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;
11
12 import camidion.chordhelper.ChordHelperApplet;
13 import camidion.chordhelper.midieditor.MidiSequenceEditor;
14
15 /**
16  * すべてのMIDIデバイスモデル {@link MidiTransceiverListModel} を収容するリストです。
17  * {@link MidiDeviceTreeModel} もこのリストを参照します。
18  */
19 public class MidiTransceiverListModelList extends Vector<MidiTransceiverListModel> {
20
21         public String toString() { return "MIDI devices"; }
22
23         public MidiSequenceEditor editorDialog;
24
25         private MidiSequencerModel sequencerModel;
26         public MidiSequencerModel getSequencerModel() { return sequencerModel; }
27
28         public MidiTransceiverListModelList(List<VirtualMidiDevice> guiVirtualDeviceList) {
29                 //
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));
34                 }
35                 // シーケンサの取得
36                 Sequencer sequencer;
37                 try {
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");
42                         e.printStackTrace();
43                 }
44                 // MIDIエディタの生成
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 ) {
53                         // MIDIデバイスの取得
54                         MidiDevice device;
55                         try {
56                                 device = MidiSystem.getMidiDevice(info);
57                         } catch( MidiUnavailableException e ) {
58                                 e.printStackTrace(); continue;
59                         }
60                         // シーケンサはすでに取得済みなのでスキップ
61                         if( device instanceof Sequencer ) continue;
62                         //
63                         // Java内蔵シンセサイザ
64                         if( device instanceof Synthesizer ) {
65                                 try {
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");
70                                         e.printStackTrace();
71                                 }
72                                 continue;
73                         }
74                         // その他のMIDIデバイス
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;
79                 }
80                 // MIDIデバイスを開く。
81                 //   NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
82                 //
83                 //   そうすれば、後から開いた MIDI IN Tx デバイスからの
84                 //   タイムスタンプのほうが「若く」なる。これにより、
85                 //   先に開かれ「少し歳を食った」Rx デバイスは
86                 //   「信号が遅れてやってきた」と認識するので、
87                 //   遅れを取り戻そうとして即座に音を出してくれる。
88                 //
89                 //   開く順序が逆になると「進みすぎるから遅らせよう」として
90                 //   無用なレイテンシーが発生する原因になる。
91                 try {
92                         MidiTransceiverListModel openModels[] = {
93                                 synthModel,
94                                 firstMidiOutModel,
95                                 sequencerModel,
96                                 firstMidiInModel,
97                                 editorDialogModel,
98                         };
99                         for( MidiTransceiverListModel m : openModels ) if( m != null ) {
100                                 m.getMidiDevice().open();
101                                 m.openReceiver();
102                         }
103                         for( MidiTransceiverListModel m : guiModels ) {
104                                 m.getMidiDevice().open();
105                                 m.openReceiver();
106                         }
107                 } catch( MidiUnavailableException ex ) {
108                         ex.printStackTrace();
109                 }
110                 // 初期接続
111                 //
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);
117                 }
118                 if( firstMidiInModel != null ) {
119                         for( MidiTransceiverListModel m : guiModels ) firstMidiInModel.connectToReceiverOf(m);
120                         firstMidiInModel.connectToReceiverOf(sequencerModel);
121                         firstMidiInModel.connectToReceiverOf(synthModel);
122                         firstMidiInModel.connectToReceiverOf(firstMidiOutModel);
123                 }
124                 if( sequencerModel != null ) {
125                         for( MidiTransceiverListModel m : guiModels ) sequencerModel.connectToReceiverOf(m);
126                         sequencerModel.connectToReceiverOf(synthModel);
127                         sequencerModel.connectToReceiverOf(firstMidiOutModel);
128                 }
129                 if( editorDialogModel != null ) {
130                         editorDialogModel.connectToReceiverOf(synthModel);
131                         editorDialogModel.connectToReceiverOf(firstMidiOutModel);
132                 }
133         }
134 }