1 /* MidiSystem.java -- Access system MIDI resources
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.sound
.midi
;
41 import gnu
.classpath
.ServiceFactory
;
44 import java
.io
.IOException
;
45 import java
.io
.InputStream
;
46 import java
.io
.OutputStream
;
48 import java
.util
.ArrayList
;
49 import java
.util
.List
;
50 import java
.util
.Iterator
;
52 import javax
.sound
.midi
.spi
.MidiDeviceProvider
;
53 import javax
.sound
.midi
.spi
.MidiFileReader
;
54 import javax
.sound
.midi
.spi
.MidiFileWriter
;
55 import javax
.sound
.midi
.spi
.SoundbankReader
;
58 * MidiSystem provides access to the computer system's MIDI resources,
59 * as well as utility routines for reading MIDI files and more.
61 * @author Anthony Green (green@redhat.com)
65 public class MidiSystem
73 * Get an array of all available MIDI devices.
75 * @return a possibly empty array of all available MIDI devices
77 public static MidiDevice
.Info
[] getMidiDeviceInfo()
79 Iterator deviceProviders
=
80 ServiceFactory
.lookupProviders(MidiDeviceProvider
.class);
81 List infoList
= new ArrayList();
83 while (deviceProviders
.hasNext())
85 MidiDeviceProvider provider
= (MidiDeviceProvider
) deviceProviders
.next();
86 MidiDevice
.Info
[] infos
= provider
.getDeviceInfo();
87 for (int i
= infos
.length
; i
> 0; )
88 infoList
.add(infos
[--i
]);
91 return (MidiDevice
.Info
[])
92 infoList
.toArray(new MidiDevice
.Info
[infoList
.size()]);
96 * Get the specified MIDI device.
98 * @param info a description of the device we're looking for
99 * @return the requested MIDI device
100 * @throws MidiUnavailableException if no MIDI devices are configured or found
101 * @throws IllegalArgumentException if the device described by info is not found
103 public static MidiDevice
getMidiDevice(MidiDevice
.Info info
)
104 throws MidiUnavailableException
106 Iterator deviceProviders
=
107 ServiceFactory
.lookupProviders(MidiDeviceProvider
.class);
109 if (! deviceProviders
.hasNext())
110 throw new MidiUnavailableException("No MIDI device providers available.");
114 MidiDeviceProvider provider
=
115 (MidiDeviceProvider
) deviceProviders
.next();
116 if (provider
.isDeviceSupported(info
))
117 return provider
.getDevice(info
);
118 } while (deviceProviders
.hasNext());
120 throw new IllegalArgumentException("MIDI device "
121 + info
+ " not available.");
125 * Get the default Receiver instance. This just picks the first one
128 * @return the default Receiver instance
129 * @throws MidiUnavailableException if no Receiver is found
131 public static Receiver
getReceiver() throws MidiUnavailableException
133 // TODO: The 1.5 spec has a fancy mechanism to specify the default
134 // receiver device. For now, well just return the first one we find.
135 MidiDevice
.Info
[] infos
= getMidiDeviceInfo();
136 for (int i
= 0; i
< infos
.length
; i
++)
138 MidiDevice device
= getMidiDevice(infos
[i
]);
139 if (device
instanceof Receiver
)
140 return (Receiver
) device
;
142 throw new MidiUnavailableException("No Receiver device available");
146 * Get the default Transmitter instance. This just picks the first one
149 * @return the default Transmitter instance
150 * @throws MidiUnavailableException if no Transmitter is found
152 public static Transmitter
getTransmitter() throws MidiUnavailableException
154 // TODO: The 1.5 spec has a fancy mechanism to specify the default
155 // Transmitter device. For now, well just return the first one we find.
156 MidiDevice
.Info
[] infos
= getMidiDeviceInfo();
157 for (int i
= 0; i
< infos
.length
; i
++)
159 MidiDevice device
= getMidiDevice(infos
[i
]);
160 if (device
instanceof Transmitter
)
161 return (Transmitter
) device
;
163 throw new MidiUnavailableException("No Transmitter device available");
167 * Get the default Synthesizer instance. This just picks the first one
170 * @return the default Synthesizer instance
171 * @throws MidiUnavailableException if no Synthesizer is found
173 public static Synthesizer
getSynthesizer() throws MidiUnavailableException
175 // TODO: The 1.5 spec has a fancy mechanism to specify the default
176 // Synthesizer device. For now, well just return the first one we find.
177 MidiDevice
.Info
[] infos
= getMidiDeviceInfo();
178 for (int i
= 0; i
< infos
.length
; i
++)
180 MidiDevice device
= getMidiDevice(infos
[i
]);
181 if (device
instanceof Synthesizer
)
182 return (Synthesizer
) device
;
184 throw new MidiUnavailableException("No Synthesizer device available");
188 * Get the default Sequencer instance. This just picks the first one
191 * @return the default Sequencer instance
192 * @throws MidiUnavailableException if no Sequencer is found
194 public static Sequencer
getSequencer() throws MidiUnavailableException
196 // TODO: The 1.5 spec has a fancy mechanism to specify the default
197 // Sequencer device. For now, well just return the first one we find.
198 MidiDevice
.Info
[] infos
= getMidiDeviceInfo();
199 for (int i
= 0; i
< infos
.length
; i
++)
201 MidiDevice device
= getMidiDevice(infos
[i
]);
202 if (device
instanceof Sequencer
)
203 return (Sequencer
) device
;
205 throw new MidiUnavailableException("No Sequencer device available");
209 * Read a Soundbank object from the given stream.
211 * @param stream the stream from which to read the Soundbank
212 * @return the Soundbank object
213 * @throws InvalidMidiDataException if we were unable to read the soundbank
214 * @throws IOException if an I/O error happened while reading
216 public static Soundbank
getSoundbank(InputStream stream
)
217 throws InvalidMidiDataException
, IOException
219 Iterator readers
= ServiceFactory
.lookupProviders(SoundbankReader
.class);
220 while (readers
.hasNext())
222 SoundbankReader sr
= (SoundbankReader
) readers
.next();
223 Soundbank sb
= sr
.getSoundbank(stream
);
227 throw new InvalidMidiDataException("Cannot read soundbank from stream");
231 * Read a Soundbank object from the given url.
233 * @param url the url from which to read the Soundbank
234 * @return the Soundbank object
235 * @throws InvalidMidiDataException if we were unable to read the soundbank
236 * @throws IOException if an I/O error happened while reading
238 public static Soundbank
getSoundbank(URL url
)
239 throws InvalidMidiDataException
, IOException
241 Iterator readers
= ServiceFactory
.lookupProviders(SoundbankReader
.class);
242 while (readers
.hasNext())
244 SoundbankReader sr
= (SoundbankReader
) readers
.next();
245 Soundbank sb
= sr
.getSoundbank(url
);
249 throw new InvalidMidiDataException("Cannot read from url " + url
);
253 * Read a Soundbank object from the given file.
255 * @param file the file from which to read the Soundbank
256 * @return the Soundbank object
257 * @throws InvalidMidiDataException if we were unable to read the soundbank
258 * @throws IOException if an I/O error happened while reading
260 public static Soundbank
getSoundbank(File file
)
261 throws InvalidMidiDataException
, IOException
263 Iterator readers
= ServiceFactory
.lookupProviders(SoundbankReader
.class);
264 while (readers
.hasNext())
266 SoundbankReader sr
= (SoundbankReader
) readers
.next();
267 Soundbank sb
= sr
.getSoundbank(file
);
271 throw new InvalidMidiDataException("Cannot read soundbank from file "
276 * Read a MidiFileFormat object from the given stream.
278 * @param stream the stream from which to read the MidiFileFormat
279 * @return the MidiFileFormat object
280 * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat
281 * @throws IOException if an I/O error happened while reading
283 public static MidiFileFormat
getMidiFileFormat(InputStream stream
)
284 throws InvalidMidiDataException
, IOException
286 Iterator readers
= ServiceFactory
.lookupProviders(MidiFileReader
.class);
287 while (readers
.hasNext())
289 MidiFileReader sr
= (MidiFileReader
) readers
.next();
290 MidiFileFormat sb
= sr
.getMidiFileFormat(stream
);
294 throw new InvalidMidiDataException("Can't read MidiFileFormat from stream");
298 * Read a MidiFileFormat object from the given url.
300 * @param url the url from which to read the MidiFileFormat
301 * @return the MidiFileFormat object
302 * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat
303 * @throws IOException if an I/O error happened while reading
305 public static MidiFileFormat
getMidiFileFormat(URL url
)
306 throws InvalidMidiDataException
, IOException
308 Iterator readers
= ServiceFactory
.lookupProviders(MidiFileReader
.class);
309 while (readers
.hasNext())
311 MidiFileReader sr
= (MidiFileReader
) readers
.next();
312 MidiFileFormat sb
= sr
.getMidiFileFormat(url
);
316 throw new InvalidMidiDataException("Cannot read from url " + url
);
320 * Read a MidiFileFormat object from the given file.
322 * @param file the file from which to read the MidiFileFormat
323 * @return the MidiFileFormat object
324 * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat
325 * @throws IOException if an I/O error happened while reading
327 public static MidiFileFormat
getMidiFileFormat(File file
)
328 throws InvalidMidiDataException
, IOException
330 Iterator readers
= ServiceFactory
.lookupProviders(MidiFileReader
.class);
331 while (readers
.hasNext())
333 MidiFileReader sr
= (MidiFileReader
) readers
.next();
334 MidiFileFormat sb
= sr
.getMidiFileFormat(file
);
338 throw new InvalidMidiDataException("Can't read MidiFileFormat from file "
343 * Read a Sequence object from the given stream.
345 * @param stream the stream from which to read the Sequence
346 * @return the Sequence object
347 * @throws InvalidMidiDataException if we were unable to read the Sequence
348 * @throws IOException if an I/O error happened while reading
350 public static Sequence
getSequence(InputStream stream
)
351 throws InvalidMidiDataException
, IOException
353 Iterator readers
= ServiceFactory
.lookupProviders(MidiFileReader
.class);
354 while (readers
.hasNext())
356 MidiFileReader sr
= (MidiFileReader
) readers
.next();
357 Sequence sq
= sr
.getSequence(stream
);
361 throw new InvalidMidiDataException("Can't read Sequence from stream");
365 * Read a Sequence object from the given url.
367 * @param url the url from which to read the Sequence
368 * @return the Sequence object
369 * @throws InvalidMidiDataException if we were unable to read the Sequence
370 * @throws IOException if an I/O error happened while reading
372 public static Sequence
getSequence(URL url
)
373 throws InvalidMidiDataException
, IOException
375 Iterator readers
= ServiceFactory
.lookupProviders(MidiFileReader
.class);
376 while (readers
.hasNext())
378 MidiFileReader sr
= (MidiFileReader
) readers
.next();
379 Sequence sq
= sr
.getSequence(url
);
383 throw new InvalidMidiDataException("Cannot read from url " + url
);
387 * Read a Sequence object from the given file.
389 * @param file the file from which to read the Sequence
390 * @return the Sequence object
391 * @throws InvalidMidiDataException if we were unable to read the Sequence
392 * @throws IOException if an I/O error happened while reading
394 public static Sequence
getSequence(File file
)
395 throws InvalidMidiDataException
, IOException
397 Iterator readers
= ServiceFactory
.lookupProviders(MidiFileReader
.class);
398 while (readers
.hasNext())
400 MidiFileReader sr
= (MidiFileReader
) readers
.next();
401 Sequence sq
= sr
.getSequence(file
);
405 throw new InvalidMidiDataException("Can't read Sequence from file "
410 * Return an array of supported MIDI file types on this system.
412 * @return the array of supported MIDI file types
414 public static int[] getMidiFileTypes()
416 // We only support a max of 3 MIDI file types.
417 boolean supported
[] = new boolean[3];
418 // The number of supported formats.
420 Iterator writers
= ServiceFactory
.lookupProviders(MidiFileWriter
.class);
421 while (writers
.hasNext())
423 MidiFileWriter fw
= (MidiFileWriter
) writers
.next();
424 int types
[] = fw
.getMidiFileTypes();
425 for (int i
= types
.length
; i
> 0;)
427 int type
= types
[--i
];
428 if (supported
[type
] == false)
431 supported
[type
] = true;
435 int result
[] = new int[count
];
436 for (int i
= supported
.length
; i
> 0;)
445 * Return true if the system supports writing files of type fileType.
447 * @param fileType the MIDI file type we want to write
448 * @return true if we can write fileType files, false otherwise
450 public static boolean isFileTypeSupported(int fileType
)
452 Iterator writers
= ServiceFactory
.lookupProviders(MidiFileWriter
.class);
453 while (writers
.hasNext())
455 MidiFileWriter fw
= (MidiFileWriter
) writers
.next();
457 if (fw
.isFileTypeSupported(fileType
))
464 * Return an array of supported MIDI file types on this system
465 * for the given sequnce.
467 * @param sequence the sequnce to write
468 * @return the array of supported MIDI file types
470 public static int[] getMidiFileTypes(Sequence sequence
)
472 // We only support a max of 3 MIDI file types.
473 boolean supported
[] = new boolean[3];
474 // The number of supported formats.
476 Iterator writers
= ServiceFactory
.lookupProviders(MidiFileWriter
.class);
477 while (writers
.hasNext())
479 MidiFileWriter fw
= (MidiFileWriter
) writers
.next();
480 int types
[] = fw
.getMidiFileTypes(sequence
);
481 for (int i
= types
.length
; i
> 0;)
483 int type
= types
[--i
];
484 if (supported
[type
] == false)
487 supported
[type
] = true;
491 int result
[] = new int[count
];
492 for (int i
= supported
.length
; i
> 0;)
501 * Return true if the system supports writing files of type fileType
502 * for the given sequence.
504 * @param fileType the MIDI file type we want to write
505 * @param sequence the Sequence we want to write
506 * @return true if we can write fileType files for sequence, false otherwise
508 public static boolean isFileTypeSupported(int fileType
, Sequence sequence
)
510 Iterator writers
= ServiceFactory
.lookupProviders(MidiFileWriter
.class);
511 while (writers
.hasNext())
513 MidiFileWriter fw
= (MidiFileWriter
) writers
.next();
515 if (fw
.isFileTypeSupported(fileType
, sequence
))
522 * Write a sequence to an output stream using a specific MIDI file format.
524 * @param in the sequence to write
525 * @param fileType the MIDI file format to use
526 * @param out the output stream to write to
527 * @return the number of bytes written
528 * @throws IOException if an I/O exception happens
529 * @throws IllegalArgumentException if fileType is not supported for in
531 public static int write(Sequence in
, int fileType
, OutputStream out
)
534 Iterator writers
= ServiceFactory
.lookupProviders(MidiFileWriter
.class);
535 while (writers
.hasNext())
537 MidiFileWriter fw
= (MidiFileWriter
) writers
.next();
539 if (fw
.isFileTypeSupported(fileType
, in
))
540 return fw
.write(in
, fileType
, out
);
542 throw new IllegalArgumentException("File type "
543 + fileType
+ " is not supported");
547 * Write a sequence to a file using a specific MIDI file format.
549 * @param in the sequence to write
550 * @param fileType the MIDI file format to use
551 * @param out the file to write to
552 * @return the number of bytes written
553 * @throws IOException if an I/O exception happens
554 * @throws IllegalArgumentException if fileType is not supported for in
556 public static int write(Sequence in
, int fileType
, File out
)
559 Iterator writers
= ServiceFactory
.lookupProviders(MidiFileWriter
.class);
560 while (writers
.hasNext())
562 MidiFileWriter fw
= (MidiFileWriter
) writers
.next();
564 if (fw
.isFileTypeSupported(fileType
, in
))
565 return fw
.write(in
, fileType
, out
);
567 throw new IllegalArgumentException("File type "
568 + fileType
+ " is not supported");