OSDN Git Service

・文字コード判定方法の改善
[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
14 /**
15  * 仮想MIDIデバイスを含めたすべてのMIDIデバイスモデル {@link MidiTransceiverListModel} を収容するリスト
16  */
17 public class MidiTransceiverListModelList extends Vector<MidiTransceiverListModel> {
18
19         public String toString() { return "MIDI devices"; }
20
21         private MidiSequencerModel sequencerModel;
22         public MidiSequencerModel getSequencerModel() { return sequencerModel; }
23
24         public MidiTransceiverListModelList(List<VirtualMidiDevice> guiVirtualDeviceList) {
25                 //
26                 // GUI仮想MIDIデバイス
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));
30                 }
31                 // シーケンサの取得
32                 Sequencer sequencer;
33                 try {
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");
38                         e.printStackTrace();
39                 }
40                 // その他のリアルMIDIデバイスの取得
41                 MidiTransceiverListModel synthModel = null;
42                 MidiTransceiverListModel firstMidiInModel = null;
43                 MidiTransceiverListModel firstMidiOutModel = null;
44                 MidiDevice.Info[] deviceInfos = MidiSystem.getMidiDeviceInfo();
45                 for( MidiDevice.Info info : deviceInfos ) {
46                         MidiDevice device;
47                         try {
48                                 device = MidiSystem.getMidiDevice(info);
49                         } catch( MidiUnavailableException e ) {
50                                 e.printStackTrace(); continue;
51                         }
52                         // シーケンサはすでに取得済みなのでスキップ
53                         if( device instanceof Sequencer ) continue;
54                         //
55                         // Java内蔵シンセサイザ
56                         if( device instanceof Synthesizer ) {
57                                 try {
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");
62                                         e.printStackTrace();
63                                 }
64                                 continue;
65                         }
66                         // その他のMIDIデバイス
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;
71                 }
72                 // MIDIデバイスを開く。
73                 //   NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。
74                 //
75                 //   そうすれば、後から開いた MIDI IN Tx デバイスからの
76                 //   タイムスタンプのほうが「若く」なる。これにより、
77                 //   先に開かれ「少し歳を食った」Rx デバイスは
78                 //   「信号が遅れてやってきた」と認識するので、
79                 //   遅れを取り戻そうとして即座に音を出してくれる。
80                 //
81                 //   開く順序が逆になると「進みすぎるから遅らせよう」として
82                 //   無用なレイテンシーが発生する原因になる。
83                 try {
84                         MidiTransceiverListModel openModels[] = {
85                                 synthModel,
86                                 firstMidiOutModel,
87                                 sequencerModel,
88                                 firstMidiInModel,
89                         };
90                         for( MidiTransceiverListModel m : openModels ) if( m != null ) {
91                                 m.getMidiDevice().open();
92                                 m.openReceiver();
93                         }
94                         for( MidiTransceiverListModel m : guiModels ) {
95                                 m.getMidiDevice().open();
96                                 m.openReceiver();
97                         }
98                 } catch( MidiUnavailableException ex ) {
99                         ex.printStackTrace();
100                 }
101                 // 初期接続
102                 //
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);
108                 }
109                 if( firstMidiInModel != null ) {
110                         for( MidiTransceiverListModel m : guiModels ) firstMidiInModel.connectToReceiverOf(m);
111                         firstMidiInModel.connectToReceiverOf(sequencerModel);
112                         firstMidiInModel.connectToReceiverOf(synthModel);
113                         firstMidiInModel.connectToReceiverOf(firstMidiOutModel);
114                 }
115                 if( sequencerModel != null ) {
116                         for( MidiTransceiverListModel m : guiModels ) sequencerModel.connectToReceiverOf(m);
117                         sequencerModel.connectToReceiverOf(synthModel);
118                         sequencerModel.connectToReceiverOf(firstMidiOutModel);
119                 }
120         }
121         /**
122          * すべてのデバイスについて、{@link MidiTransceiverListModel#resetMicrosecondPosition()}
123          * でマイクロ秒位置をリセットします。
124          */
125         public void resetMicrosecondPosition() {
126                 for(MidiTransceiverListModel m : this) m.resetMicrosecondPosition();
127         }
128         /**
129          * すべてのMIDIデバイスを閉じます。
130          */
131         public void closeAllDevices() {
132                 for(MidiTransceiverListModel m : this) m.device.close();
133         }
134 }