OSDN Git Service

d5e7cdaa6bed6ab084c6a7ba0a8691daf30affce
[midichordhelper/MIDIChordHelper.git] / src / camidion / chordhelper / mididevice / MidiDeviceModelList.java
1 package camidion.chordhelper.mididevice;\r
2 \r
3 import java.util.List;\r
4 import java.util.Vector;\r
5 \r
6 import javax.sound.midi.MidiDevice;\r
7 import javax.sound.midi.MidiSystem;\r
8 import javax.sound.midi.MidiUnavailableException;\r
9 import javax.sound.midi.Sequencer;\r
10 import javax.sound.midi.Synthesizer;\r
11 \r
12 import camidion.chordhelper.ChordHelperApplet;\r
13 import camidion.chordhelper.midieditor.MidiEditor;\r
14 \r
15 /**\r
16  * MIDIデバイスモデルリスト\r
17  */\r
18 public class MidiDeviceModelList extends Vector<MidiConnecterListModel> {\r
19         /**\r
20          * MIDIエディタ\r
21          */\r
22         public MidiEditor editorDialog;\r
23         /**\r
24          * MIDIエディタモデル\r
25          */\r
26         private MidiConnecterListModel editorDialogModel;\r
27         /**\r
28          * MIDIシンセサイザーモデル\r
29          */\r
30         private MidiConnecterListModel synthModel;\r
31         /**\r
32          * 最初のMIDI出力\r
33          */\r
34         private MidiConnecterListModel firstMidiOutModel;\r
35         /**\r
36          * MIDIデバイスモデルリストを生成します。\r
37          * @param vmdList 仮想MIDIデバイスのリスト\r
38          */\r
39         public MidiDeviceModelList(List<VirtualMidiDevice> vmdList) {\r
40                 MidiDevice.Info[] devInfos = MidiSystem.getMidiDeviceInfo();\r
41                 MidiConnecterListModel guiModels[] = new MidiConnecterListModel[vmdList.size()];\r
42                 MidiConnecterListModel firstMidiInModel = null;\r
43                 for( int i=0; i<vmdList.size(); i++ )\r
44                         guiModels[i] = addMidiDevice(vmdList.get(i));\r
45                 Sequencer sequencer;\r
46                 try {\r
47                         sequencer = MidiSystem.getSequencer(false);\r
48                         sequencerModel = (MidiSequencerModel)addMidiDevice(sequencer);\r
49                 } catch( MidiUnavailableException e ) {\r
50                         System.out.println(\r
51                                 ChordHelperApplet.VersionInfo.NAME +\r
52                                 " : MIDI sequencer unavailable"\r
53                         );\r
54                         e.printStackTrace();\r
55                 }\r
56                 editorDialog = new MidiEditor(sequencerModel);\r
57                 editorDialogModel = addMidiDevice(editorDialog.getVirtualMidiDevice());\r
58                 for( MidiDevice.Info info : devInfos ) {\r
59                         MidiDevice device;\r
60                         try {\r
61                                 device = MidiSystem.getMidiDevice(info);\r
62                         } catch( MidiUnavailableException e ) {\r
63                                 e.printStackTrace(); continue;\r
64                         }\r
65                         if( device instanceof Sequencer ) continue;\r
66                         if( device instanceof Synthesizer ) {\r
67                                 try {\r
68                                         synthModel = addMidiDevice(MidiSystem.getSynthesizer());\r
69                                 } catch( MidiUnavailableException e ) {\r
70                                         System.out.println(\r
71                                                 ChordHelperApplet.VersionInfo.NAME +\r
72                                                 " : Java internal MIDI synthesizer unavailable"\r
73                                         );\r
74                                         e.printStackTrace();\r
75                                 }\r
76                                 continue;\r
77                         }\r
78                         MidiConnecterListModel m = addMidiDevice(device);\r
79                         if( m.rxSupported() && firstMidiOutModel == null )\r
80                                 firstMidiOutModel = m;\r
81                         if( m.txSupported() && firstMidiInModel == null )\r
82                                 firstMidiInModel = m;\r
83                 }\r
84                 // デバイスを開く。\r
85                 //   NOTE: 必ず MIDI OUT Rx デバイスを先に開くこと。\r
86                 //\r
87                 //   そうすれば、後から開いた MIDI IN Tx デバイスからの\r
88                 //   タイムスタンプのほうが「若く」なる。これにより、\r
89                 //   先に開かれ「少し歳を食った」Rx デバイスは\r
90                 //   「信号が遅れてやってきた」と認識するので、\r
91                 //   遅れを取り戻そうとして即座に音を出してくれる。\r
92                 //\r
93                 //   開く順序が逆になると「進みすぎるから遅らせよう」として\r
94                 //   無用なレイテンシーが発生する原因になる。\r
95                 try {\r
96                         MidiConnecterListModel openModels[] = {\r
97                                 synthModel,\r
98                                 firstMidiOutModel,\r
99                                 sequencerModel,\r
100                                 firstMidiInModel,\r
101                                 editorDialogModel,\r
102                         };\r
103                         for( MidiConnecterListModel m : openModels ) {\r
104                                 if( m != null ) m.openDevice();\r
105                         }\r
106                         for( MidiConnecterListModel m : guiModels ) {\r
107                                 m.openDevice();\r
108                         }\r
109                 } catch( MidiUnavailableException ex ) {\r
110                         ex.printStackTrace();\r
111                 }\r
112                 // 初期接続\r
113                 //\r
114                 for( MidiConnecterListModel mtx : guiModels ) {\r
115                         for( MidiConnecterListModel mrx : guiModels )\r
116                                 mtx.connectToReceiverOf(mrx);\r
117                         mtx.connectToReceiverOf(sequencerModel);\r
118                         mtx.connectToReceiverOf(synthModel);\r
119                         mtx.connectToReceiverOf(firstMidiOutModel);\r
120                 }\r
121                 if( firstMidiInModel != null ) {\r
122                         for( MidiConnecterListModel m : guiModels )\r
123                                 firstMidiInModel.connectToReceiverOf(m);\r
124                         firstMidiInModel.connectToReceiverOf(sequencerModel);\r
125                         firstMidiInModel.connectToReceiverOf(synthModel);\r
126                         firstMidiInModel.connectToReceiverOf(firstMidiOutModel);\r
127                 }\r
128                 if( sequencerModel != null ) {\r
129                         for( MidiConnecterListModel m : guiModels )\r
130                                 sequencerModel.connectToReceiverOf(m);\r
131                         sequencerModel.connectToReceiverOf(synthModel);\r
132                         sequencerModel.connectToReceiverOf(firstMidiOutModel);\r
133                 }\r
134                 if( editorDialogModel != null ) {\r
135                         editorDialogModel.connectToReceiverOf(synthModel);\r
136                         editorDialogModel.connectToReceiverOf(firstMidiOutModel);\r
137                 }\r
138         }\r
139         /**\r
140          * このデバイスモデルリストに登録されたMIDIシーケンサーモデルを返します。\r
141          * @return MIDIシーケンサーモデル\r
142          */\r
143         public MidiSequencerModel getSequencerModel() { return sequencerModel; }\r
144         private MidiSequencerModel sequencerModel;\r
145         /**\r
146          * 指定のMIDIデバイスからMIDIデバイスモデルを生成して追加します。\r
147          * @param device MIDIデバイス\r
148          * @return 生成されたMIDIデバイスモデル\r
149          */\r
150         private MidiConnecterListModel addMidiDevice(MidiDevice device) {\r
151                 MidiConnecterListModel m;\r
152                 if( device instanceof Sequencer )\r
153                         m = new MidiSequencerModel(this,(Sequencer)device,this);\r
154                 else\r
155                         m = new MidiConnecterListModel(device,this);\r
156                 addElement(m);\r
157                 return m;\r
158         }\r
159 }