Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/sound/midi/MidiSystem.java
38830 views
1
/*
2
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package javax.sound.midi;
27
28
import java.io.FileInputStream;
29
import java.io.File;
30
import java.io.InputStream;
31
import java.io.OutputStream;
32
import java.io.IOException;
33
34
import java.util.ArrayList;
35
import java.util.HashSet;
36
import java.util.Iterator;
37
import java.util.List;
38
import java.util.Set;
39
40
import java.net.URL;
41
42
import javax.sound.midi.spi.MidiFileWriter;
43
import javax.sound.midi.spi.MidiFileReader;
44
import javax.sound.midi.spi.SoundbankReader;
45
import javax.sound.midi.spi.MidiDeviceProvider;
46
47
import com.sun.media.sound.JDK13Services;
48
import com.sun.media.sound.ReferenceCountingDevice;
49
import com.sun.media.sound.AutoConnectSequencer;
50
import com.sun.media.sound.MidiDeviceReceiverEnvelope;
51
import com.sun.media.sound.MidiDeviceTransmitterEnvelope;
52
53
54
/**
55
* The <code>MidiSystem</code> class provides access to the installed MIDI
56
* system resources, including devices such as synthesizers, sequencers, and
57
* MIDI input and output ports. A typical simple MIDI application might
58
* begin by invoking one or more <code>MidiSystem</code> methods to learn
59
* what devices are installed and to obtain the ones needed in that
60
* application.
61
* <p>
62
* The class also has methods for reading files, streams, and URLs that
63
* contain standard MIDI file data or soundbanks. You can query the
64
* <code>MidiSystem</code> for the format of a specified MIDI file.
65
* <p>
66
* You cannot instantiate a <code>MidiSystem</code>; all the methods are
67
* static.
68
*
69
* <p>Properties can be used to specify default MIDI devices.
70
* Both system properties and a properties file are considered.
71
* The <code>sound.properties</code> properties file is read from
72
* an implementation-specific location (typically it is the <code>lib</code>
73
* directory in the Java installation directory).
74
* If a property exists both as a system property and in the
75
* properties file, the system property takes precedence. If none is
76
* specified, a suitable default is chosen among the available devices.
77
* The syntax of the properties file is specified in
78
* {@link java.util.Properties#load(InputStream) Properties.load}. The
79
* following table lists the available property keys and which methods
80
* consider them:
81
*
82
* <table border=0>
83
* <caption>MIDI System Property Keys</caption>
84
* <tr>
85
* <th>Property Key</th>
86
* <th>Interface</th>
87
* <th>Affected Method</th>
88
* </tr>
89
* <tr>
90
* <td><code>javax.sound.midi.Receiver</code></td>
91
* <td>{@link Receiver}</td>
92
* <td>{@link #getReceiver}</td>
93
* </tr>
94
* <tr>
95
* <td><code>javax.sound.midi.Sequencer</code></td>
96
* <td>{@link Sequencer}</td>
97
* <td>{@link #getSequencer}</td>
98
* </tr>
99
* <tr>
100
* <td><code>javax.sound.midi.Synthesizer</code></td>
101
* <td>{@link Synthesizer}</td>
102
* <td>{@link #getSynthesizer}</td>
103
* </tr>
104
* <tr>
105
* <td><code>javax.sound.midi.Transmitter</code></td>
106
* <td>{@link Transmitter}</td>
107
* <td>{@link #getTransmitter}</td>
108
* </tr>
109
* </table>
110
*
111
* The property value consists of the provider class name
112
* and the device name, separated by the hash mark (&quot;#&quot;).
113
* The provider class name is the fully-qualified
114
* name of a concrete {@link javax.sound.midi.spi.MidiDeviceProvider
115
* MIDI device provider} class. The device name is matched against
116
* the <code>String</code> returned by the <code>getName</code>
117
* method of <code>MidiDevice.Info</code>.
118
* Either the class name, or the device name may be omitted.
119
* If only the class name is specified, the trailing hash mark
120
* is optional.
121
*
122
* <p>If the provider class is specified, and it can be
123
* successfully retrieved from the installed providers,
124
* the list of
125
* <code>MidiDevice.Info</code> objects is retrieved
126
* from the provider. Otherwise, or when these devices
127
* do not provide a subsequent match, the list is retrieved
128
* from {@link #getMidiDeviceInfo} to contain
129
* all available <code>MidiDevice.Info</code> objects.
130
*
131
* <p>If a device name is specified, the resulting list of
132
* <code>MidiDevice.Info</code> objects is searched:
133
* the first one with a matching name, and whose
134
* <code>MidiDevice</code> implements the
135
* respective interface, will be returned.
136
* If no matching <code>MidiDevice.Info</code> object
137
* is found, or the device name is not specified,
138
* the first suitable device from the resulting
139
* list will be returned. For Sequencer and Synthesizer,
140
* a device is suitable if it implements the respective
141
* interface; whereas for Receiver and Transmitter, a device is
142
* suitable if it
143
* implements neither Sequencer nor Synthesizer and provides
144
* at least one Receiver or Transmitter, respectively.
145
*
146
* For example, the property <code>javax.sound.midi.Receiver</code>
147
* with a value
148
* <code>&quot;com.sun.media.sound.MidiProvider#SunMIDI1&quot;</code>
149
* will have the following consequences when
150
* <code>getReceiver</code> is called:
151
* if the class <code>com.sun.media.sound.MidiProvider</code> exists
152
* in the list of installed MIDI device providers,
153
* the first <code>Receiver</code> device with name
154
* <code>&quot;SunMIDI1&quot;</code> will be returned. If it cannot
155
* be found, the first <code>Receiver</code> from that provider
156
* will be returned, regardless of name.
157
* If there is none, the first <code>Receiver</code> with name
158
* <code>&quot;SunMIDI1&quot;</code> in the list of all devices
159
* (as returned by <code>getMidiDeviceInfo</code>) will be returned,
160
* or, if not found, the first <code>Receiver</code> that can
161
* be found in the list of all devices is returned.
162
* If that fails, too, a <code>MidiUnavailableException</code>
163
* is thrown.
164
*
165
* @author Kara Kytle
166
* @author Florian Bomers
167
* @author Matthias Pfisterer
168
*/
169
public class MidiSystem {
170
171
/**
172
* Private no-args constructor for ensuring against instantiation.
173
*/
174
private MidiSystem() {
175
}
176
177
178
/**
179
* Obtains an array of information objects representing
180
* the set of all MIDI devices available on the system.
181
* A returned information object can then be used to obtain the
182
* corresponding device object, by invoking
183
* {@link #getMidiDevice(MidiDevice.Info) getMidiDevice}.
184
*
185
* @return an array of <code>MidiDevice.Info</code> objects, one
186
* for each installed MIDI device. If no such devices are installed,
187
* an array of length 0 is returned.
188
*/
189
public static MidiDevice.Info[] getMidiDeviceInfo() {
190
List allInfos = new ArrayList();
191
List providers = getMidiDeviceProviders();
192
193
for(int i = 0; i < providers.size(); i++) {
194
MidiDeviceProvider provider = (MidiDeviceProvider) providers.get(i);
195
MidiDevice.Info[] tmpinfo = provider.getDeviceInfo();
196
for (int j = 0; j < tmpinfo.length; j++) {
197
allInfos.add( tmpinfo[j] );
198
}
199
}
200
MidiDevice.Info[] infosArray = (MidiDevice.Info[]) allInfos.toArray(new MidiDevice.Info[0]);
201
return infosArray;
202
}
203
204
205
/**
206
* Obtains the requested MIDI device.
207
*
208
* @param info a device information object representing the desired device.
209
* @return the requested device
210
* @throws MidiUnavailableException if the requested device is not available
211
* due to resource restrictions
212
* @throws IllegalArgumentException if the info object does not represent
213
* a MIDI device installed on the system
214
* @see #getMidiDeviceInfo
215
*/
216
public static MidiDevice getMidiDevice(MidiDevice.Info info) throws MidiUnavailableException {
217
List providers = getMidiDeviceProviders();
218
219
for(int i = 0; i < providers.size(); i++) {
220
MidiDeviceProvider provider = (MidiDeviceProvider) providers.get(i);
221
if (provider.isDeviceSupported(info)) {
222
MidiDevice device = provider.getDevice(info);
223
return device;
224
}
225
}
226
throw new IllegalArgumentException("Requested device not installed: " + info);
227
}
228
229
230
/**
231
* Obtains a MIDI receiver from an external MIDI port
232
* or other default device.
233
* The returned receiver always implements
234
* the {@code MidiDeviceReceiver} interface.
235
*
236
* <p>If the system property
237
* <code>javax.sound.midi.Receiver</code>
238
* is defined or it is defined in the file &quot;sound.properties&quot;,
239
* it is used to identify the device that provides the default receiver.
240
* For details, refer to the {@link MidiSystem class description}.
241
*
242
* If a suitable MIDI port is not available, the Receiver is
243
* retrieved from an installed synthesizer.
244
*
245
* <p>If a native receiver provided by the default device does not implement
246
* the {@code MidiDeviceReceiver} interface, it will be wrapped in a
247
* wrapper class that implements the {@code MidiDeviceReceiver} interface.
248
* The corresponding {@code Receiver} method calls will be forwarded
249
* to the native receiver.
250
*
251
* <p>If this method returns successfully, the {@link
252
* javax.sound.midi.MidiDevice MidiDevice} the
253
* <code>Receiver</code> belongs to is opened implicitly, if it is
254
* not already open. It is possible to close an implicitly opened
255
* device by calling {@link javax.sound.midi.Receiver#close close}
256
* on the returned <code>Receiver</code>. All open <code>Receiver</code>
257
* instances have to be closed in order to release system resources
258
* hold by the <code>MidiDevice</code>. For a
259
* detailed description of open/close behaviour see the class
260
* description of {@link javax.sound.midi.MidiDevice MidiDevice}.
261
*
262
*
263
* @return the default MIDI receiver
264
* @throws MidiUnavailableException if the default receiver is not
265
* available due to resource restrictions,
266
* or no device providing receivers is installed in the system
267
*/
268
public static Receiver getReceiver() throws MidiUnavailableException {
269
// may throw MidiUnavailableException
270
MidiDevice device = getDefaultDeviceWrapper(Receiver.class);
271
Receiver receiver;
272
if (device instanceof ReferenceCountingDevice) {
273
receiver = ((ReferenceCountingDevice) device).getReceiverReferenceCounting();
274
} else {
275
receiver = device.getReceiver();
276
}
277
if (!(receiver instanceof MidiDeviceReceiver)) {
278
receiver = new MidiDeviceReceiverEnvelope(device, receiver);
279
}
280
return receiver;
281
}
282
283
284
/**
285
* Obtains a MIDI transmitter from an external MIDI port
286
* or other default source.
287
* The returned transmitter always implements
288
* the {@code MidiDeviceTransmitter} interface.
289
*
290
* <p>If the system property
291
* <code>javax.sound.midi.Transmitter</code>
292
* is defined or it is defined in the file &quot;sound.properties&quot;,
293
* it is used to identify the device that provides the default transmitter.
294
* For details, refer to the {@link MidiSystem class description}.
295
*
296
* <p>If a native transmitter provided by the default device does not implement
297
* the {@code MidiDeviceTransmitter} interface, it will be wrapped in a
298
* wrapper class that implements the {@code MidiDeviceTransmitter} interface.
299
* The corresponding {@code Transmitter} method calls will be forwarded
300
* to the native transmitter.
301
*
302
* <p>If this method returns successfully, the {@link
303
* javax.sound.midi.MidiDevice MidiDevice} the
304
* <code>Transmitter</code> belongs to is opened implicitly, if it
305
* is not already open. It is possible to close an implicitly
306
* opened device by calling {@link
307
* javax.sound.midi.Transmitter#close close} on the returned
308
* <code>Transmitter</code>. All open <code>Transmitter</code>
309
* instances have to be closed in order to release system resources
310
* hold by the <code>MidiDevice</code>. For a detailed description
311
* of open/close behaviour see the class description of {@link
312
* javax.sound.midi.MidiDevice MidiDevice}.
313
*
314
* @return the default MIDI transmitter
315
* @throws MidiUnavailableException if the default transmitter is not
316
* available due to resource restrictions,
317
* or no device providing transmitters is installed in the system
318
*/
319
public static Transmitter getTransmitter() throws MidiUnavailableException {
320
// may throw MidiUnavailableException
321
MidiDevice device = getDefaultDeviceWrapper(Transmitter.class);
322
Transmitter transmitter;
323
if (device instanceof ReferenceCountingDevice) {
324
transmitter = ((ReferenceCountingDevice) device).getTransmitterReferenceCounting();
325
} else {
326
transmitter = device.getTransmitter();
327
}
328
if (!(transmitter instanceof MidiDeviceTransmitter)) {
329
transmitter = new MidiDeviceTransmitterEnvelope(device, transmitter);
330
}
331
return transmitter;
332
}
333
334
335
/**
336
* Obtains the default synthesizer.
337
*
338
* <p>If the system property
339
* <code>javax.sound.midi.Synthesizer</code>
340
* is defined or it is defined in the file &quot;sound.properties&quot;,
341
* it is used to identify the default synthesizer.
342
* For details, refer to the {@link MidiSystem class description}.
343
*
344
* @return the default synthesizer
345
* @throws MidiUnavailableException if the synthesizer is not
346
* available due to resource restrictions,
347
* or no synthesizer is installed in the system
348
*/
349
public static Synthesizer getSynthesizer() throws MidiUnavailableException {
350
// may throw MidiUnavailableException
351
return (Synthesizer) getDefaultDeviceWrapper(Synthesizer.class);
352
}
353
354
355
/**
356
* Obtains the default <code>Sequencer</code>, connected to
357
* a default device.
358
* The returned <code>Sequencer</code> instance is
359
* connected to the default <code>Synthesizer</code>,
360
* as returned by {@link #getSynthesizer}.
361
* If there is no <code>Synthesizer</code>
362
* available, or the default <code>Synthesizer</code>
363
* cannot be opened, the <code>sequencer</code> is connected
364
* to the default <code>Receiver</code>, as returned
365
* by {@link #getReceiver}.
366
* The connection is made by retrieving a <code>Transmitter</code>
367
* instance from the <code>Sequencer</code> and setting its
368
* <code>Receiver</code>.
369
* Closing and re-opening the sequencer will restore the
370
* connection to the default device.
371
*
372
* <p>This method is equivalent to calling
373
* <code>getSequencer(true)</code>.
374
*
375
* <p>If the system property
376
* <code>javax.sound.midi.Sequencer</code>
377
* is defined or it is defined in the file &quot;sound.properties&quot;,
378
* it is used to identify the default sequencer.
379
* For details, refer to the {@link MidiSystem class description}.
380
*
381
* @return the default sequencer, connected to a default Receiver
382
* @throws MidiUnavailableException if the sequencer is not
383
* available due to resource restrictions,
384
* or there is no <code>Receiver</code> available by any
385
* installed <code>MidiDevice</code>,
386
* or no sequencer is installed in the system.
387
* @see #getSequencer(boolean)
388
* @see #getSynthesizer
389
* @see #getReceiver
390
*/
391
public static Sequencer getSequencer() throws MidiUnavailableException {
392
return getSequencer(true);
393
}
394
395
396
397
/**
398
* Obtains the default <code>Sequencer</code>, optionally
399
* connected to a default device.
400
*
401
* <p>If <code>connected</code> is true, the returned
402
* <code>Sequencer</code> instance is
403
* connected to the default <code>Synthesizer</code>,
404
* as returned by {@link #getSynthesizer}.
405
* If there is no <code>Synthesizer</code>
406
* available, or the default <code>Synthesizer</code>
407
* cannot be opened, the <code>sequencer</code> is connected
408
* to the default <code>Receiver</code>, as returned
409
* by {@link #getReceiver}.
410
* The connection is made by retrieving a <code>Transmitter</code>
411
* instance from the <code>Sequencer</code> and setting its
412
* <code>Receiver</code>.
413
* Closing and re-opening the sequencer will restore the
414
* connection to the default device.
415
*
416
* <p>If <code>connected</code> is false, the returned
417
* <code>Sequencer</code> instance is not connected, it
418
* has no open <code>Transmitters</code>. In order to
419
* play the sequencer on a MIDI device, or a <code>Synthesizer</code>,
420
* it is necessary to get a <code>Transmitter</code> and set its
421
* <code>Receiver</code>.
422
*
423
* <p>If the system property
424
* <code>javax.sound.midi.Sequencer</code>
425
* is defined or it is defined in the file "sound.properties",
426
* it is used to identify the default sequencer.
427
* For details, refer to the {@link MidiSystem class description}.
428
*
429
* @param connected whether or not the returned {@code Sequencer}
430
* is connected to the default {@code Synthesizer}
431
* @return the default sequencer
432
* @throws MidiUnavailableException if the sequencer is not
433
* available due to resource restrictions,
434
* or no sequencer is installed in the system,
435
* or if <code>connected</code> is true, and there is
436
* no <code>Receiver</code> available by any installed
437
* <code>MidiDevice</code>
438
* @see #getSynthesizer
439
* @see #getReceiver
440
* @since 1.5
441
*/
442
public static Sequencer getSequencer(boolean connected)
443
throws MidiUnavailableException {
444
Sequencer seq = (Sequencer) getDefaultDeviceWrapper(Sequencer.class);
445
446
if (connected) {
447
// IMPORTANT: this code needs to be synch'ed with
448
// all AutoConnectSequencer instances,
449
// (e.g. RealTimeSequencer) because the
450
// same algorithm for synth retrieval
451
// needs to be used!
452
453
Receiver rec = null;
454
MidiUnavailableException mue = null;
455
456
// first try to connect to the default synthesizer
457
try {
458
Synthesizer synth = getSynthesizer();
459
if (synth instanceof ReferenceCountingDevice) {
460
rec = ((ReferenceCountingDevice) synth).getReceiverReferenceCounting();
461
} else {
462
synth.open();
463
try {
464
rec = synth.getReceiver();
465
} finally {
466
// make sure that the synth is properly closed
467
if (rec == null) {
468
synth.close();
469
}
470
}
471
}
472
} catch (MidiUnavailableException e) {
473
// something went wrong with synth
474
if (e instanceof MidiUnavailableException) {
475
mue = (MidiUnavailableException) e;
476
}
477
}
478
if (rec == null) {
479
// then try to connect to the default Receiver
480
try {
481
rec = MidiSystem.getReceiver();
482
} catch (Exception e) {
483
// something went wrong. Nothing to do then!
484
if (e instanceof MidiUnavailableException) {
485
mue = (MidiUnavailableException) e;
486
}
487
}
488
}
489
if (rec != null) {
490
seq.getTransmitter().setReceiver(rec);
491
if (seq instanceof AutoConnectSequencer) {
492
((AutoConnectSequencer) seq).setAutoConnect(rec);
493
}
494
} else {
495
if (mue != null) {
496
throw mue;
497
}
498
throw new MidiUnavailableException("no receiver available");
499
}
500
}
501
return seq;
502
}
503
504
505
506
507
/**
508
* Constructs a MIDI sound bank by reading it from the specified stream.
509
* The stream must point to
510
* a valid MIDI soundbank file. In general, MIDI soundbank providers may
511
* need to read some data from the stream before determining whether they
512
* support it. These parsers must
513
* be able to mark the stream, read enough data to determine whether they
514
* support the stream, and, if not, reset the stream's read pointer to
515
* its original position. If the input stream does not support this,
516
* this method may fail with an IOException.
517
* @param stream the source of the sound bank data.
518
* @return the sound bank
519
* @throws InvalidMidiDataException if the stream does not point to
520
* valid MIDI soundbank data recognized by the system
521
* @throws IOException if an I/O error occurred when loading the soundbank
522
* @see InputStream#markSupported
523
* @see InputStream#mark
524
*/
525
public static Soundbank getSoundbank(InputStream stream)
526
throws InvalidMidiDataException, IOException {
527
528
SoundbankReader sp = null;
529
Soundbank s = null;
530
531
List providers = getSoundbankReaders();
532
533
for(int i = 0; i < providers.size(); i++) {
534
sp = (SoundbankReader)providers.get(i);
535
s = sp.getSoundbank(stream);
536
537
if( s!= null) {
538
return s;
539
}
540
}
541
throw new InvalidMidiDataException("cannot get soundbank from stream");
542
543
}
544
545
546
/**
547
* Constructs a <code>Soundbank</code> by reading it from the specified URL.
548
* The URL must point to a valid MIDI soundbank file.
549
*
550
* @param url the source of the sound bank data
551
* @return the sound bank
552
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
553
* soundbank data recognized by the system
554
* @throws IOException if an I/O error occurred when loading the soundbank
555
*/
556
public static Soundbank getSoundbank(URL url)
557
throws InvalidMidiDataException, IOException {
558
559
SoundbankReader sp = null;
560
Soundbank s = null;
561
562
List providers = getSoundbankReaders();
563
564
for(int i = 0; i < providers.size(); i++) {
565
sp = (SoundbankReader)providers.get(i);
566
s = sp.getSoundbank(url);
567
568
if( s!= null) {
569
return s;
570
}
571
}
572
throw new InvalidMidiDataException("cannot get soundbank from stream");
573
574
}
575
576
577
/**
578
* Constructs a <code>Soundbank</code> by reading it from the specified
579
* <code>File</code>.
580
* The <code>File</code> must point to a valid MIDI soundbank file.
581
*
582
* @param file the source of the sound bank data
583
* @return the sound bank
584
* @throws InvalidMidiDataException if the <code>File</code> does not
585
* point to valid MIDI soundbank data recognized by the system
586
* @throws IOException if an I/O error occurred when loading the soundbank
587
*/
588
public static Soundbank getSoundbank(File file)
589
throws InvalidMidiDataException, IOException {
590
591
SoundbankReader sp = null;
592
Soundbank s = null;
593
594
List providers = getSoundbankReaders();
595
596
for(int i = 0; i < providers.size(); i++) {
597
sp = (SoundbankReader)providers.get(i);
598
s = sp.getSoundbank(file);
599
600
if( s!= null) {
601
return s;
602
}
603
}
604
throw new InvalidMidiDataException("cannot get soundbank from stream");
605
}
606
607
608
609
/**
610
* Obtains the MIDI file format of the data in the specified input stream.
611
* The stream must point to valid MIDI file data for a file type recognized
612
* by the system.
613
* <p>
614
* This method and/or the code it invokes may need to read some data from
615
* the stream to determine whether its data format is supported. The
616
* implementation may therefore
617
* need to mark the stream, read enough data to determine whether it is in
618
* a supported format, and reset the stream's read pointer to its original
619
* position. If the input stream does not permit this set of operations,
620
* this method may fail with an <code>IOException</code>.
621
* <p>
622
* This operation can only succeed for files of a type which can be parsed
623
* by an installed file reader. It may fail with an InvalidMidiDataException
624
* even for valid files if no compatible file reader is installed. It
625
* will also fail with an InvalidMidiDataException if a compatible file reader
626
* is installed, but encounters errors while determining the file format.
627
*
628
* @param stream the input stream from which file format information
629
* should be extracted
630
* @return an <code>MidiFileFormat</code> object describing the MIDI file
631
* format
632
* @throws InvalidMidiDataException if the stream does not point to valid
633
* MIDI file data recognized by the system
634
* @throws IOException if an I/O exception occurs while accessing the
635
* stream
636
* @see #getMidiFileFormat(URL)
637
* @see #getMidiFileFormat(File)
638
* @see InputStream#markSupported
639
* @see InputStream#mark
640
*/
641
public static MidiFileFormat getMidiFileFormat(InputStream stream)
642
throws InvalidMidiDataException, IOException {
643
644
List providers = getMidiFileReaders();
645
MidiFileFormat format = null;
646
647
for(int i = 0; i < providers.size(); i++) {
648
MidiFileReader reader = (MidiFileReader) providers.get(i);
649
try {
650
format = reader.getMidiFileFormat( stream ); // throws IOException
651
break;
652
} catch (InvalidMidiDataException e) {
653
continue;
654
}
655
}
656
657
if( format==null ) {
658
throw new InvalidMidiDataException("input stream is not a supported file type");
659
} else {
660
return format;
661
}
662
}
663
664
665
/**
666
* Obtains the MIDI file format of the data in the specified URL. The URL
667
* must point to valid MIDI file data for a file type recognized
668
* by the system.
669
* <p>
670
* This operation can only succeed for files of a type which can be parsed
671
* by an installed file reader. It may fail with an InvalidMidiDataException
672
* even for valid files if no compatible file reader is installed. It
673
* will also fail with an InvalidMidiDataException if a compatible file reader
674
* is installed, but encounters errors while determining the file format.
675
*
676
* @param url the URL from which file format information should be
677
* extracted
678
* @return a <code>MidiFileFormat</code> object describing the MIDI file
679
* format
680
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
681
* file data recognized by the system
682
* @throws IOException if an I/O exception occurs while accessing the URL
683
*
684
* @see #getMidiFileFormat(InputStream)
685
* @see #getMidiFileFormat(File)
686
*/
687
public static MidiFileFormat getMidiFileFormat(URL url)
688
throws InvalidMidiDataException, IOException {
689
690
List providers = getMidiFileReaders();
691
MidiFileFormat format = null;
692
693
for(int i = 0; i < providers.size(); i++) {
694
MidiFileReader reader = (MidiFileReader) providers.get(i);
695
try {
696
format = reader.getMidiFileFormat( url ); // throws IOException
697
break;
698
} catch (InvalidMidiDataException e) {
699
continue;
700
}
701
}
702
703
if( format==null ) {
704
throw new InvalidMidiDataException("url is not a supported file type");
705
} else {
706
return format;
707
}
708
}
709
710
711
/**
712
* Obtains the MIDI file format of the specified <code>File</code>. The
713
* <code>File</code> must point to valid MIDI file data for a file type
714
* recognized by the system.
715
* <p>
716
* This operation can only succeed for files of a type which can be parsed
717
* by an installed file reader. It may fail with an InvalidMidiDataException
718
* even for valid files if no compatible file reader is installed. It
719
* will also fail with an InvalidMidiDataException if a compatible file reader
720
* is installed, but encounters errors while determining the file format.
721
*
722
* @param file the <code>File</code> from which file format information
723
* should be extracted
724
* @return a <code>MidiFileFormat</code> object describing the MIDI file
725
* format
726
* @throws InvalidMidiDataException if the <code>File</code> does not point
727
* to valid MIDI file data recognized by the system
728
* @throws IOException if an I/O exception occurs while accessing the file
729
*
730
* @see #getMidiFileFormat(InputStream)
731
* @see #getMidiFileFormat(URL)
732
*/
733
public static MidiFileFormat getMidiFileFormat(File file)
734
throws InvalidMidiDataException, IOException {
735
736
List providers = getMidiFileReaders();
737
MidiFileFormat format = null;
738
739
for(int i = 0; i < providers.size(); i++) {
740
MidiFileReader reader = (MidiFileReader) providers.get(i);
741
try {
742
format = reader.getMidiFileFormat( file ); // throws IOException
743
break;
744
} catch (InvalidMidiDataException e) {
745
continue;
746
}
747
}
748
749
if( format==null ) {
750
throw new InvalidMidiDataException("file is not a supported file type");
751
} else {
752
return format;
753
}
754
}
755
756
757
/**
758
* Obtains a MIDI sequence from the specified input stream. The stream must
759
* point to valid MIDI file data for a file type recognized
760
* by the system.
761
* <p>
762
* This method and/or the code it invokes may need to read some data
763
* from the stream to determine whether
764
* its data format is supported. The implementation may therefore
765
* need to mark the stream, read enough data to determine whether it is in
766
* a supported format, and reset the stream's read pointer to its original
767
* position. If the input stream does not permit this set of operations,
768
* this method may fail with an <code>IOException</code>.
769
* <p>
770
* This operation can only succeed for files of a type which can be parsed
771
* by an installed file reader. It may fail with an InvalidMidiDataException
772
* even for valid files if no compatible file reader is installed. It
773
* will also fail with an InvalidMidiDataException if a compatible file reader
774
* is installed, but encounters errors while constructing the <code>Sequence</code>
775
* object from the file data.
776
*
777
* @param stream the input stream from which the <code>Sequence</code>
778
* should be constructed
779
* @return a <code>Sequence</code> object based on the MIDI file data
780
* contained in the input stream
781
* @throws InvalidMidiDataException if the stream does not point to
782
* valid MIDI file data recognized by the system
783
* @throws IOException if an I/O exception occurs while accessing the
784
* stream
785
* @see InputStream#markSupported
786
* @see InputStream#mark
787
*/
788
public static Sequence getSequence(InputStream stream)
789
throws InvalidMidiDataException, IOException {
790
791
List providers = getMidiFileReaders();
792
Sequence sequence = null;
793
794
for(int i = 0; i < providers.size(); i++) {
795
MidiFileReader reader = (MidiFileReader) providers.get(i);
796
try {
797
sequence = reader.getSequence( stream ); // throws IOException
798
break;
799
} catch (InvalidMidiDataException e) {
800
continue;
801
}
802
}
803
804
if( sequence==null ) {
805
throw new InvalidMidiDataException("could not get sequence from input stream");
806
} else {
807
return sequence;
808
}
809
}
810
811
812
/**
813
* Obtains a MIDI sequence from the specified URL. The URL must
814
* point to valid MIDI file data for a file type recognized
815
* by the system.
816
* <p>
817
* This operation can only succeed for files of a type which can be parsed
818
* by an installed file reader. It may fail with an InvalidMidiDataException
819
* even for valid files if no compatible file reader is installed. It
820
* will also fail with an InvalidMidiDataException if a compatible file reader
821
* is installed, but encounters errors while constructing the <code>Sequence</code>
822
* object from the file data.
823
*
824
* @param url the URL from which the <code>Sequence</code> should be
825
* constructed
826
* @return a <code>Sequence</code> object based on the MIDI file data
827
* pointed to by the URL
828
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
829
* file data recognized by the system
830
* @throws IOException if an I/O exception occurs while accessing the URL
831
*/
832
public static Sequence getSequence(URL url)
833
throws InvalidMidiDataException, IOException {
834
835
List providers = getMidiFileReaders();
836
Sequence sequence = null;
837
838
for(int i = 0; i < providers.size(); i++) {
839
MidiFileReader reader = (MidiFileReader) providers.get(i);
840
try {
841
sequence = reader.getSequence( url ); // throws IOException
842
break;
843
} catch (InvalidMidiDataException e) {
844
continue;
845
}
846
}
847
848
if( sequence==null ) {
849
throw new InvalidMidiDataException("could not get sequence from URL");
850
} else {
851
return sequence;
852
}
853
}
854
855
856
/**
857
* Obtains a MIDI sequence from the specified <code>File</code>.
858
* The <code>File</code> must point to valid MIDI file data
859
* for a file type recognized by the system.
860
* <p>
861
* This operation can only succeed for files of a type which can be parsed
862
* by an installed file reader. It may fail with an InvalidMidiDataException
863
* even for valid files if no compatible file reader is installed. It
864
* will also fail with an InvalidMidiDataException if a compatible file reader
865
* is installed, but encounters errors while constructing the <code>Sequence</code>
866
* object from the file data.
867
*
868
* @param file the <code>File</code> from which the <code>Sequence</code>
869
* should be constructed
870
* @return a <code>Sequence</code> object based on the MIDI file data
871
* pointed to by the File
872
* @throws InvalidMidiDataException if the File does not point to valid MIDI
873
* file data recognized by the system
874
* @throws IOException if an I/O exception occurs
875
*/
876
public static Sequence getSequence(File file)
877
throws InvalidMidiDataException, IOException {
878
879
List providers = getMidiFileReaders();
880
Sequence sequence = null;
881
882
for(int i = 0; i < providers.size(); i++) {
883
MidiFileReader reader = (MidiFileReader) providers.get(i);
884
try {
885
sequence = reader.getSequence( file ); // throws IOException
886
break;
887
} catch (InvalidMidiDataException e) {
888
continue;
889
}
890
}
891
892
if( sequence==null ) {
893
throw new InvalidMidiDataException("could not get sequence from file");
894
} else {
895
return sequence;
896
}
897
}
898
899
900
/**
901
* Obtains the set of MIDI file types for which file writing support is
902
* provided by the system.
903
* @return array of unique file types. If no file types are supported,
904
* an array of length 0 is returned.
905
*/
906
public static int[] getMidiFileTypes() {
907
908
List providers = getMidiFileWriters();
909
Set allTypes = new HashSet();
910
911
// gather from all the providers
912
913
for (int i = 0; i < providers.size(); i++ ) {
914
MidiFileWriter writer = (MidiFileWriter) providers.get(i);
915
int[] types = writer.getMidiFileTypes();
916
for (int j = 0; j < types.length; j++ ) {
917
allTypes.add(new Integer(types[j]));
918
}
919
}
920
int resultTypes[] = new int[allTypes.size()];
921
int index = 0;
922
Iterator iterator = allTypes.iterator();
923
while (iterator.hasNext()) {
924
Integer integer = (Integer) iterator.next();
925
resultTypes[index++] = integer.intValue();
926
}
927
return resultTypes;
928
}
929
930
931
/**
932
* Indicates whether file writing support for the specified MIDI file type
933
* is provided by the system.
934
* @param fileType the file type for which write capabilities are queried
935
* @return <code>true</code> if the file type is supported,
936
* otherwise <code>false</code>
937
*/
938
public static boolean isFileTypeSupported(int fileType) {
939
940
List providers = getMidiFileWriters();
941
942
for (int i = 0; i < providers.size(); i++ ) {
943
MidiFileWriter writer = (MidiFileWriter) providers.get(i);
944
if( writer.isFileTypeSupported(fileType)) {
945
return true;
946
}
947
}
948
return false;
949
}
950
951
952
/**
953
* Obtains the set of MIDI file types that the system can write from the
954
* sequence specified.
955
* @param sequence the sequence for which MIDI file type support
956
* is queried
957
* @return the set of unique supported file types. If no file types are supported,
958
* returns an array of length 0.
959
*/
960
public static int[] getMidiFileTypes(Sequence sequence) {
961
962
List providers = getMidiFileWriters();
963
Set allTypes = new HashSet();
964
965
// gather from all the providers
966
967
for (int i = 0; i < providers.size(); i++ ) {
968
MidiFileWriter writer = (MidiFileWriter) providers.get(i);
969
int[] types = writer.getMidiFileTypes(sequence);
970
for (int j = 0; j < types.length; j++ ) {
971
allTypes.add(new Integer(types[j]));
972
}
973
}
974
int resultTypes[] = new int[allTypes.size()];
975
int index = 0;
976
Iterator iterator = allTypes.iterator();
977
while (iterator.hasNext()) {
978
Integer integer = (Integer) iterator.next();
979
resultTypes[index++] = integer.intValue();
980
}
981
return resultTypes;
982
}
983
984
985
/**
986
* Indicates whether a MIDI file of the file type specified can be written
987
* from the sequence indicated.
988
* @param fileType the file type for which write capabilities
989
* are queried
990
* @param sequence the sequence for which file writing support is queried
991
* @return <code>true</code> if the file type is supported for this
992
* sequence, otherwise <code>false</code>
993
*/
994
public static boolean isFileTypeSupported(int fileType, Sequence sequence) {
995
996
List providers = getMidiFileWriters();
997
998
for (int i = 0; i < providers.size(); i++ ) {
999
MidiFileWriter writer = (MidiFileWriter) providers.get(i);
1000
if( writer.isFileTypeSupported(fileType,sequence)) {
1001
return true;
1002
}
1003
}
1004
return false;
1005
}
1006
1007
1008
/**
1009
* Writes a stream of bytes representing a file of the MIDI file type
1010
* indicated to the output stream provided.
1011
* @param in sequence containing MIDI data to be written to the file
1012
* @param fileType the file type of the file to be written to the output stream
1013
* @param out stream to which the file data should be written
1014
* @return the number of bytes written to the output stream
1015
* @throws IOException if an I/O exception occurs
1016
* @throws IllegalArgumentException if the file format is not supported by
1017
* the system
1018
* @see #isFileTypeSupported(int, Sequence)
1019
* @see #getMidiFileTypes(Sequence)
1020
*/
1021
public static int write(Sequence in, int fileType, OutputStream out) throws IOException {
1022
1023
List providers = getMidiFileWriters();
1024
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
1025
int bytesWritten = -2;
1026
1027
for (int i = 0; i < providers.size(); i++ ) {
1028
MidiFileWriter writer = (MidiFileWriter) providers.get(i);
1029
if( writer.isFileTypeSupported( fileType, in ) ) {
1030
1031
bytesWritten = writer.write(in, fileType, out);
1032
break;
1033
}
1034
}
1035
if (bytesWritten == -2) {
1036
throw new IllegalArgumentException("MIDI file type is not supported");
1037
}
1038
return bytesWritten;
1039
}
1040
1041
1042
/**
1043
* Writes a stream of bytes representing a file of the MIDI file type
1044
* indicated to the external file provided.
1045
* @param in sequence containing MIDI data to be written to the file
1046
* @param type the file type of the file to be written to the output stream
1047
* @param out external file to which the file data should be written
1048
* @return the number of bytes written to the file
1049
* @throws IOException if an I/O exception occurs
1050
* @throws IllegalArgumentException if the file type is not supported by
1051
* the system
1052
* @see #isFileTypeSupported(int, Sequence)
1053
* @see #getMidiFileTypes(Sequence)
1054
*/
1055
public static int write(Sequence in, int type, File out) throws IOException {
1056
1057
List providers = getMidiFileWriters();
1058
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
1059
int bytesWritten = -2;
1060
1061
for (int i = 0; i < providers.size(); i++ ) {
1062
MidiFileWriter writer = (MidiFileWriter) providers.get(i);
1063
if( writer.isFileTypeSupported( type, in ) ) {
1064
1065
bytesWritten = writer.write(in, type, out);
1066
break;
1067
}
1068
}
1069
if (bytesWritten == -2) {
1070
throw new IllegalArgumentException("MIDI file type is not supported");
1071
}
1072
return bytesWritten;
1073
}
1074
1075
1076
1077
// HELPER METHODS
1078
1079
private static List getMidiDeviceProviders() {
1080
return getProviders(MidiDeviceProvider.class);
1081
}
1082
1083
1084
private static List getSoundbankReaders() {
1085
return getProviders(SoundbankReader.class);
1086
}
1087
1088
1089
private static List getMidiFileWriters() {
1090
return getProviders(MidiFileWriter.class);
1091
}
1092
1093
1094
private static List getMidiFileReaders() {
1095
return getProviders(MidiFileReader.class);
1096
}
1097
1098
1099
/** Attempts to locate and return a default MidiDevice of the specified
1100
* type.
1101
*
1102
* This method wraps {@link #getDefaultDevice}. It catches the
1103
* <code>IllegalArgumentException</code> thrown by
1104
* <code>getDefaultDevice</code> and instead throws a
1105
* <code>MidiUnavailableException</code>, with the catched
1106
* exception chained.
1107
*
1108
* @param deviceClass The requested device type, one of Synthesizer.class,
1109
* Sequencer.class, Receiver.class or Transmitter.class.
1110
* @throws MidiUnavalableException on failure.
1111
*/
1112
private static MidiDevice getDefaultDeviceWrapper(Class deviceClass)
1113
throws MidiUnavailableException{
1114
try {
1115
return getDefaultDevice(deviceClass);
1116
} catch (IllegalArgumentException iae) {
1117
MidiUnavailableException mae = new MidiUnavailableException();
1118
mae.initCause(iae);
1119
throw mae;
1120
}
1121
}
1122
1123
1124
/** Attempts to locate and return a default MidiDevice of the specified
1125
* type.
1126
*
1127
* @param deviceClass The requested device type, one of Synthesizer.class,
1128
* Sequencer.class, Receiver.class or Transmitter.class.
1129
* @throws IllegalArgumentException on failure.
1130
*/
1131
private static MidiDevice getDefaultDevice(Class deviceClass) {
1132
List providers = getMidiDeviceProviders();
1133
String providerClassName = JDK13Services.getDefaultProviderClassName(deviceClass);
1134
String instanceName = JDK13Services.getDefaultInstanceName(deviceClass);
1135
MidiDevice device;
1136
1137
if (providerClassName != null) {
1138
MidiDeviceProvider defaultProvider = getNamedProvider(providerClassName, providers);
1139
if (defaultProvider != null) {
1140
if (instanceName != null) {
1141
device = getNamedDevice(instanceName, defaultProvider, deviceClass);
1142
if (device != null) {
1143
return device;
1144
}
1145
}
1146
device = getFirstDevice(defaultProvider, deviceClass);
1147
if (device != null) {
1148
return device;
1149
}
1150
}
1151
}
1152
1153
/* Provider class not specified or cannot be found, or
1154
provider class specified, and no appropriate device available or
1155
provider class and instance specified and instance cannot be found or is not appropriate */
1156
if (instanceName != null) {
1157
device = getNamedDevice(instanceName, providers, deviceClass);
1158
if (device != null) {
1159
return device;
1160
}
1161
}
1162
1163
/* No default are specified, or if something is specified, everything
1164
failed. */
1165
device = getFirstDevice(providers, deviceClass);
1166
if (device != null) {
1167
return device;
1168
}
1169
throw new IllegalArgumentException("Requested device not installed");
1170
}
1171
1172
1173
1174
/** Return a MidiDeviceProcider of a given class from the list of
1175
MidiDeviceProviders.
1176
1177
@param providerClassName The class name of the provider to be returned.
1178
@param provider The list of MidiDeviceProviders that is searched.
1179
@return A MidiDeviceProvider of the requested class, or null if none
1180
is found.
1181
*/
1182
private static MidiDeviceProvider getNamedProvider(String providerClassName, List providers) {
1183
for(int i = 0; i < providers.size(); i++) {
1184
MidiDeviceProvider provider = (MidiDeviceProvider) providers.get(i);
1185
if (provider.getClass().getName().equals(providerClassName)) {
1186
return provider;
1187
}
1188
}
1189
return null;
1190
}
1191
1192
1193
/** Return a MidiDevice with a given name from a given MidiDeviceProvider.
1194
@param deviceName The name of the MidiDevice to be returned.
1195
@param provider The MidiDeviceProvider to check for MidiDevices.
1196
@param deviceClass The requested device type, one of Synthesizer.class,
1197
Sequencer.class, Receiver.class or Transmitter.class.
1198
1199
@return A MidiDevice matching the requirements, or null if none is found.
1200
*/
1201
private static MidiDevice getNamedDevice(String deviceName,
1202
MidiDeviceProvider provider,
1203
Class deviceClass) {
1204
MidiDevice device;
1205
// try to get MIDI port
1206
device = getNamedDevice(deviceName, provider, deviceClass,
1207
false, false);
1208
if (device != null) {
1209
return device;
1210
}
1211
1212
if (deviceClass == Receiver.class) {
1213
// try to get Synthesizer
1214
device = getNamedDevice(deviceName, provider, deviceClass,
1215
true, false);
1216
if (device != null) {
1217
return device;
1218
}
1219
}
1220
1221
return null;
1222
}
1223
1224
1225
/** Return a MidiDevice with a given name from a given MidiDeviceProvider.
1226
@param deviceName The name of the MidiDevice to be returned.
1227
@param provider The MidiDeviceProvider to check for MidiDevices.
1228
@param deviceClass The requested device type, one of Synthesizer.class,
1229
Sequencer.class, Receiver.class or Transmitter.class.
1230
1231
@return A MidiDevice matching the requirements, or null if none is found.
1232
*/
1233
private static MidiDevice getNamedDevice(String deviceName,
1234
MidiDeviceProvider provider,
1235
Class deviceClass,
1236
boolean allowSynthesizer,
1237
boolean allowSequencer) {
1238
MidiDevice.Info[] infos = provider.getDeviceInfo();
1239
for (int i = 0; i < infos.length; i++) {
1240
if (infos[i].getName().equals(deviceName)) {
1241
MidiDevice device = provider.getDevice(infos[i]);
1242
if (isAppropriateDevice(device, deviceClass,
1243
allowSynthesizer, allowSequencer)) {
1244
return device;
1245
}
1246
}
1247
}
1248
return null;
1249
}
1250
1251
1252
/** Return a MidiDevice with a given name from a list of
1253
MidiDeviceProviders.
1254
@param deviceName The name of the MidiDevice to be returned.
1255
@param providers The List of MidiDeviceProviders to check for
1256
MidiDevices.
1257
@param deviceClass The requested device type, one of Synthesizer.class,
1258
Sequencer.class, Receiver.class or Transmitter.class.
1259
@return A Mixer matching the requirements, or null if none is found.
1260
*/
1261
private static MidiDevice getNamedDevice(String deviceName,
1262
List providers,
1263
Class deviceClass) {
1264
MidiDevice device;
1265
// try to get MIDI port
1266
device = getNamedDevice(deviceName, providers, deviceClass,
1267
false, false);
1268
if (device != null) {
1269
return device;
1270
}
1271
1272
if (deviceClass == Receiver.class) {
1273
// try to get Synthesizer
1274
device = getNamedDevice(deviceName, providers, deviceClass,
1275
true, false);
1276
if (device != null) {
1277
return device;
1278
}
1279
}
1280
1281
return null;
1282
}
1283
1284
1285
/** Return a MidiDevice with a given name from a list of
1286
MidiDeviceProviders.
1287
@param deviceName The name of the MidiDevice to be returned.
1288
@param providers The List of MidiDeviceProviders to check for
1289
MidiDevices.
1290
@param deviceClass The requested device type, one of Synthesizer.class,
1291
Sequencer.class, Receiver.class or Transmitter.class.
1292
@return A Mixer matching the requirements, or null if none is found.
1293
*/
1294
private static MidiDevice getNamedDevice(String deviceName,
1295
List providers,
1296
Class deviceClass,
1297
boolean allowSynthesizer,
1298
boolean allowSequencer) {
1299
for(int i = 0; i < providers.size(); i++) {
1300
MidiDeviceProvider provider = (MidiDeviceProvider) providers.get(i);
1301
MidiDevice device = getNamedDevice(deviceName, provider,
1302
deviceClass,
1303
allowSynthesizer,
1304
allowSequencer);
1305
if (device != null) {
1306
return device;
1307
}
1308
}
1309
return null;
1310
}
1311
1312
1313
/** From a given MidiDeviceProvider, return the first appropriate device.
1314
@param provider The MidiDeviceProvider to check for MidiDevices.
1315
@param deviceClass The requested device type, one of Synthesizer.class,
1316
Sequencer.class, Receiver.class or Transmitter.class.
1317
@return A MidiDevice is considered appropriate, or null if no
1318
appropriate device is found.
1319
*/
1320
private static MidiDevice getFirstDevice(MidiDeviceProvider provider,
1321
Class deviceClass) {
1322
MidiDevice device;
1323
// try to get MIDI port
1324
device = getFirstDevice(provider, deviceClass,
1325
false, false);
1326
if (device != null) {
1327
return device;
1328
}
1329
1330
if (deviceClass == Receiver.class) {
1331
// try to get Synthesizer
1332
device = getFirstDevice(provider, deviceClass,
1333
true, false);
1334
if (device != null) {
1335
return device;
1336
}
1337
}
1338
1339
return null;
1340
}
1341
1342
1343
/** From a given MidiDeviceProvider, return the first appropriate device.
1344
@param provider The MidiDeviceProvider to check for MidiDevices.
1345
@param deviceClass The requested device type, one of Synthesizer.class,
1346
Sequencer.class, Receiver.class or Transmitter.class.
1347
@return A MidiDevice is considered appropriate, or null if no
1348
appropriate device is found.
1349
*/
1350
private static MidiDevice getFirstDevice(MidiDeviceProvider provider,
1351
Class deviceClass,
1352
boolean allowSynthesizer,
1353
boolean allowSequencer) {
1354
MidiDevice.Info[] infos = provider.getDeviceInfo();
1355
for (int j = 0; j < infos.length; j++) {
1356
MidiDevice device = provider.getDevice(infos[j]);
1357
if (isAppropriateDevice(device, deviceClass,
1358
allowSynthesizer, allowSequencer)) {
1359
return device;
1360
}
1361
}
1362
return null;
1363
}
1364
1365
1366
/** From a List of MidiDeviceProviders, return the first appropriate
1367
MidiDevice.
1368
@param providers The List of MidiDeviceProviders to search.
1369
@param deviceClass The requested device type, one of Synthesizer.class,
1370
Sequencer.class, Receiver.class or Transmitter.class.
1371
@return A MidiDevice that is considered appropriate, or null
1372
if none is found.
1373
*/
1374
private static MidiDevice getFirstDevice(List providers,
1375
Class deviceClass) {
1376
MidiDevice device;
1377
// try to get MIDI port
1378
device = getFirstDevice(providers, deviceClass,
1379
false, false);
1380
if (device != null) {
1381
return device;
1382
}
1383
1384
if (deviceClass == Receiver.class) {
1385
// try to get Synthesizer
1386
device = getFirstDevice(providers, deviceClass,
1387
true, false);
1388
if (device != null) {
1389
return device;
1390
}
1391
}
1392
1393
return null;
1394
}
1395
1396
1397
/** From a List of MidiDeviceProviders, return the first appropriate
1398
MidiDevice.
1399
@param providers The List of MidiDeviceProviders to search.
1400
@param deviceClass The requested device type, one of Synthesizer.class,
1401
Sequencer.class, Receiver.class or Transmitter.class.
1402
@return A MidiDevice that is considered appropriate, or null
1403
if none is found.
1404
*/
1405
private static MidiDevice getFirstDevice(List providers,
1406
Class deviceClass,
1407
boolean allowSynthesizer,
1408
boolean allowSequencer) {
1409
for(int i = 0; i < providers.size(); i++) {
1410
MidiDeviceProvider provider = (MidiDeviceProvider) providers.get(i);
1411
MidiDevice device = getFirstDevice(provider, deviceClass,
1412
allowSynthesizer,
1413
allowSequencer);
1414
if (device != null) {
1415
return device;
1416
}
1417
}
1418
return null;
1419
}
1420
1421
1422
/** Checks if a MidiDevice is appropriate.
1423
If deviceClass is Synthesizer or Sequencer, a device implementing
1424
the respective interface is considered appropriate. If deviceClass
1425
is Receiver or Transmitter, a device is considered appropriate if
1426
it implements neither Synthesizer nor Transmitter, and if it can
1427
provide at least one Receiver or Transmitter, respectively.
1428
1429
@param device the MidiDevice to test
1430
@param allowSynthesizer if true, Synthesizers are considered
1431
appropriate. Otherwise only pure MidiDevices are considered
1432
appropriate (unless allowSequencer is true). This flag only has an
1433
effect for deviceClass Receiver and Transmitter. For other device
1434
classes (Sequencer and Synthesizer), this flag has no effect.
1435
@param allowSequencer if true, Sequencers are considered
1436
appropriate. Otherwise only pure MidiDevices are considered
1437
appropriate (unless allowSynthesizer is true). This flag only has an
1438
effect for deviceClass Receiver and Transmitter. For other device
1439
classes (Sequencer and Synthesizer), this flag has no effect.
1440
@return true if the device is considered appropriate according to the
1441
rules given above, false otherwise.
1442
*/
1443
private static boolean isAppropriateDevice(MidiDevice device,
1444
Class deviceClass,
1445
boolean allowSynthesizer,
1446
boolean allowSequencer) {
1447
if (deviceClass.isInstance(device)) {
1448
// This clause is for deviceClass being either Synthesizer
1449
// or Sequencer.
1450
return true;
1451
} else {
1452
// Now the case that deviceClass is Transmitter or
1453
// Receiver. If neither allowSynthesizer nor allowSequencer is
1454
// true, we require device instances to be
1455
// neither Synthesizer nor Sequencer, since we only want
1456
// devices representing MIDI ports.
1457
// Otherwise, the respective type is accepted, too
1458
if ( (! (device instanceof Sequencer) &&
1459
! (device instanceof Synthesizer) ) ||
1460
((device instanceof Sequencer) && allowSequencer) ||
1461
((device instanceof Synthesizer) && allowSynthesizer)) {
1462
// And of cource, the device has to be able to provide
1463
// Receivers or Transmitters.
1464
if ((deviceClass == Receiver.class &&
1465
device.getMaxReceivers() != 0) ||
1466
(deviceClass == Transmitter.class &&
1467
device.getMaxTransmitters() != 0)) {
1468
return true;
1469
}
1470
}
1471
}
1472
return false;
1473
}
1474
1475
1476
/**
1477
* Obtains the set of services currently installed on the system
1478
* using sun.misc.Service, the SPI mechanism in 1.3.
1479
* @return a List of instances of providers for the requested service.
1480
* If no providers are available, a List of length 0 will be returned.
1481
*/
1482
private static List getProviders(Class providerClass) {
1483
return JDK13Services.getProviders(providerClass);
1484
}
1485
}
1486
1487