Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libjava / classpath / javax / sound / midi / MidiSystem.java
1 /* MidiSystem.java -- Access system MIDI resources
2    Copyright (C) 2005, 2012 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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)
9 any later version.
10
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.
15
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
19 02110-1301 USA.
20
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
24 combination.
25
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. */
37
38
39 package javax.sound.midi;
40
41 import gnu.classpath.ServiceFactory;
42
43 import java.io.File;
44 import java.io.IOException;
45 import java.io.InputStream;
46 import java.io.OutputStream;
47 import java.net.URL;
48 import java.util.ArrayList;
49 import java.util.List;
50 import java.util.Iterator;
51
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;
56
57 /**
58  * MidiSystem provides access to the computer system's MIDI resources,
59  * as well as utility routines for reading MIDI files and more.
60  *
61  * @author Anthony Green (green@redhat.com)
62  * @since 1.3
63  *
64  */
65 public class MidiSystem
66 {
67   private MidiSystem()
68   {
69     // Not instantiable.
70   }
71
72   /**
73    * Get an array of all available MIDI devices.
74    *
75    * @return a possibly empty array of all available MIDI devices
76    */
77   public static MidiDevice.Info[] getMidiDeviceInfo()
78   {
79     Iterator<MidiDeviceProvider> deviceProviders =
80         ServiceFactory.lookupProviders(MidiDeviceProvider.class);
81     List<MidiDevice.Info> infoList = new ArrayList<MidiDevice.Info>();
82
83     while (deviceProviders.hasNext())
84     {
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]);
89     }
90
91     return infoList.toArray(new MidiDevice.Info[infoList.size()]);
92   }
93
94   /**
95    * Get the specified MIDI device.
96    *
97    * @param info a description of the device we're looking for
98    * @return the requested MIDI device
99    * @throws MidiUnavailableException if no MIDI devices are configured or found
100    * @throws IllegalArgumentException if the device described by info is not found
101    */
102   public static MidiDevice getMidiDevice(MidiDevice.Info info)
103     throws MidiUnavailableException
104   {
105     Iterator<MidiDeviceProvider> deviceProviders =
106         ServiceFactory.lookupProviders(MidiDeviceProvider.class);
107
108     if (! deviceProviders.hasNext())
109       throw new MidiUnavailableException("No MIDI device providers available.");
110
111     do
112     {
113       MidiDeviceProvider provider =
114         (MidiDeviceProvider) deviceProviders.next();
115       if (provider.isDeviceSupported(info))
116         return provider.getDevice(info);
117     } while (deviceProviders.hasNext());
118
119     throw new IllegalArgumentException("MIDI device "
120                                        + info + " not available.");
121   }
122
123   /**
124    * Get the default Receiver instance.  This just picks the first one
125    * it finds for now.
126    *
127    * @return the default Receiver instance
128    * @throws MidiUnavailableException if no Receiver is found
129    */
130   public static Receiver getReceiver() throws MidiUnavailableException
131   {
132     // TODO: The 1.5 spec has a fancy mechanism to specify the default
133     // receiver device.  For now, well just return the first one we find.
134     MidiDevice.Info[] infos = getMidiDeviceInfo();
135     for (int i = 0; i < infos.length; i++)
136     {
137       MidiDevice device = getMidiDevice(infos[i]);
138       if (device instanceof Receiver)
139         return (Receiver) device;
140     }
141     throw new MidiUnavailableException("No Receiver device available");
142   }
143
144   /**
145    * Get the default Transmitter instance.  This just picks the first one
146    * it finds for now.
147    *
148    * @return the default Transmitter instance
149    * @throws MidiUnavailableException if no Transmitter is found
150    */
151   public static Transmitter getTransmitter() throws MidiUnavailableException
152   {
153     // TODO: The 1.5 spec has a fancy mechanism to specify the default
154     // Transmitter device.  For now, well just return the first one we find.
155     MidiDevice.Info[] infos = getMidiDeviceInfo();
156     for (int i = 0; i < infos.length; i++)
157     {
158       MidiDevice device = getMidiDevice(infos[i]);
159       if (device instanceof Transmitter)
160         return (Transmitter) device;
161     }
162     throw new MidiUnavailableException("No Transmitter device available");
163   }
164
165   /**
166    * Get the default Synthesizer instance.  This just picks the first one
167    * it finds for now.
168    *
169    * @return the default Synthesizer instance
170    * @throws MidiUnavailableException if no Synthesizer is found
171    */
172   public static Synthesizer getSynthesizer() throws MidiUnavailableException
173   {
174     // TODO: The 1.5 spec has a fancy mechanism to specify the default
175     // Synthesizer device.  For now, well just return the first one we find.
176     MidiDevice.Info[] infos = getMidiDeviceInfo();
177     for (int i = 0; i < infos.length; i++)
178     {
179       MidiDevice device = getMidiDevice(infos[i]);
180       if (device instanceof Synthesizer)
181         return (Synthesizer) device;
182     }
183     throw new MidiUnavailableException("No Synthesizer device available");
184   }
185
186   /**
187    * Get the default Sequencer instance.  This just picks the first one
188    * it finds for now.
189    *
190    * @return the default Sequencer instance
191    * @throws MidiUnavailableException if no Sequencer is found
192    */
193   public static Sequencer getSequencer() throws MidiUnavailableException
194   {
195     // TODO: The 1.5 spec has a fancy mechanism to specify the default
196     // Sequencer device.  For now, well just return the first one we find.
197     MidiDevice.Info[] infos = getMidiDeviceInfo();
198     for (int i = 0; i < infos.length; i++)
199     {
200       MidiDevice device = getMidiDevice(infos[i]);
201       if (device instanceof Sequencer)
202         return (Sequencer) device;
203     }
204     throw new MidiUnavailableException("No Sequencer device available");
205   }
206
207   /**
208    * Read a Soundbank object from the given stream.
209    *
210    * @param stream the stream from which to read the Soundbank
211    * @return the Soundbank object
212    * @throws InvalidMidiDataException if we were unable to read the soundbank
213    * @throws IOException if an I/O error happened while reading
214    */
215   public static Soundbank getSoundbank(InputStream stream)
216     throws InvalidMidiDataException, IOException
217   {
218     Iterator<SoundbankReader> readers =
219       ServiceFactory.lookupProviders(SoundbankReader.class);
220     while (readers.hasNext())
221     {
222       SoundbankReader sr = readers.next();
223       Soundbank sb = sr.getSoundbank(stream);
224       if (sb != null)
225         return sb;
226     }
227     throw new InvalidMidiDataException("Cannot read soundbank from stream");
228   }
229
230   /**
231    * Read a Soundbank object from the given url.
232    *
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
237    */
238   public static Soundbank getSoundbank(URL url)
239     throws InvalidMidiDataException, IOException
240   {
241     Iterator<SoundbankReader> readers =
242       ServiceFactory.lookupProviders(SoundbankReader.class);
243     while (readers.hasNext())
244     {
245       SoundbankReader sr = readers.next();
246       Soundbank sb = sr.getSoundbank(url);
247       if (sb != null)
248         return sb;
249     }
250     throw new InvalidMidiDataException("Cannot read from url " + url);
251   }
252
253   /**
254    * Read a Soundbank object from the given file.
255    *
256    * @param file the file from which to read the Soundbank
257    * @return the Soundbank object
258    * @throws InvalidMidiDataException if we were unable to read the soundbank
259    * @throws IOException if an I/O error happened while reading
260    */
261   public static Soundbank getSoundbank(File file)
262     throws InvalidMidiDataException, IOException
263   {
264     Iterator<SoundbankReader> readers =
265       ServiceFactory.lookupProviders(SoundbankReader.class);
266     while (readers.hasNext())
267     {
268       SoundbankReader sr = (SoundbankReader) readers.next();
269       Soundbank sb = sr.getSoundbank(file);
270       if (sb != null)
271         return sb;
272     }
273     throw new InvalidMidiDataException("Cannot read soundbank from file "
274                                        + file);
275   }
276
277   /**
278    * Read a MidiFileFormat object from the given stream.
279    *
280    * @param stream the stream from which to read the MidiFileFormat
281    * @return the MidiFileFormat object
282    * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat
283    * @throws IOException if an I/O error happened while reading
284    */
285   public static MidiFileFormat getMidiFileFormat(InputStream stream)
286     throws InvalidMidiDataException, IOException
287   {
288     Iterator<MidiFileReader> readers =
289       ServiceFactory.lookupProviders(MidiFileReader.class);
290     while (readers.hasNext())
291     {
292       MidiFileReader sr = readers.next();
293       MidiFileFormat sb = sr.getMidiFileFormat(stream);
294       if (sb != null)
295         return sb;
296     }
297     throw new InvalidMidiDataException("Can't read MidiFileFormat from stream");
298   }
299
300   /**
301    * Read a MidiFileFormat object from the given url.
302    *
303    * @param url the url from which to read the MidiFileFormat
304    * @return the MidiFileFormat object
305    * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat
306    * @throws IOException if an I/O error happened while reading
307    */
308   public static MidiFileFormat getMidiFileFormat(URL url)
309     throws InvalidMidiDataException, IOException
310   {
311     Iterator<MidiFileReader> readers =
312       ServiceFactory.lookupProviders(MidiFileReader.class);
313     while (readers.hasNext())
314     {
315       MidiFileReader sr = readers.next();
316       MidiFileFormat sb = sr.getMidiFileFormat(url);
317       if (sb != null)
318         return sb;
319     }
320     throw new InvalidMidiDataException("Cannot read from url " + url);
321   }
322
323   /**
324    * Read a MidiFileFormat object from the given file.
325    *
326    * @param file the file from which to read the MidiFileFormat
327    * @return the MidiFileFormat object
328    * @throws InvalidMidiDataException if we were unable to read the MidiFileFormat
329    * @throws IOException if an I/O error happened while reading
330    */
331   public static MidiFileFormat getMidiFileFormat(File file)
332     throws InvalidMidiDataException, IOException
333   {
334     Iterator<MidiFileReader> readers =
335       ServiceFactory.lookupProviders(MidiFileReader.class);
336     while (readers.hasNext())
337     {
338       MidiFileReader sr = readers.next();
339       MidiFileFormat sb = sr.getMidiFileFormat(file);
340       if (sb != null)
341         return sb;
342     }
343     throw new InvalidMidiDataException("Can't read MidiFileFormat from file "
344                                        + file);
345   }
346
347   /**
348    * Read a Sequence object from the given stream.
349    *
350    * @param stream the stream from which to read the Sequence
351    * @return the Sequence object
352    * @throws InvalidMidiDataException if we were unable to read the Sequence
353    * @throws IOException if an I/O error happened while reading
354    */
355   public static Sequence getSequence(InputStream stream)
356     throws InvalidMidiDataException, IOException
357   {
358     Iterator<MidiFileReader> readers =
359       ServiceFactory.lookupProviders(MidiFileReader.class);
360     while (readers.hasNext())
361     {
362       MidiFileReader sr = readers.next();
363       Sequence sq = sr.getSequence(stream);
364       if (sq != null)
365         return sq;
366     }
367     throw new InvalidMidiDataException("Can't read Sequence from stream");
368   }
369
370   /**
371    * Read a Sequence object from the given url.
372    *
373    * @param url the url from which to read the Sequence
374    * @return the Sequence object
375    * @throws InvalidMidiDataException if we were unable to read the Sequence
376    * @throws IOException if an I/O error happened while reading
377    */
378   public static Sequence getSequence(URL url)
379     throws InvalidMidiDataException, IOException
380   {
381     Iterator<MidiFileReader> readers =
382       ServiceFactory.lookupProviders(MidiFileReader.class);
383     while (readers.hasNext())
384     {
385       MidiFileReader sr = readers.next();
386       Sequence sq = sr.getSequence(url);
387       if (sq != null)
388         return sq;
389     }
390     throw new InvalidMidiDataException("Cannot read from url " + url);
391   }
392
393   /**
394    * Read a Sequence object from the given file.
395    *
396    * @param file the file from which to read the Sequence
397    * @return the Sequence object
398    * @throws InvalidMidiDataException if we were unable to read the Sequence
399    * @throws IOException if an I/O error happened while reading
400    */
401   public static Sequence getSequence(File file)
402     throws InvalidMidiDataException, IOException
403   {
404     Iterator<MidiFileReader> readers =
405       ServiceFactory.lookupProviders(MidiFileReader.class);
406     while (readers.hasNext())
407     {
408       MidiFileReader sr = readers.next();
409       Sequence sq = sr.getSequence(file);
410       if (sq != null)
411         return sq;
412     }
413     throw new InvalidMidiDataException("Can't read Sequence from file "
414                                        + file);
415   }
416
417   /**
418    * Return an array of supported MIDI file types on this system.
419    *
420    * @return the array of supported MIDI file types
421    */
422   public static int[] getMidiFileTypes()
423   {
424     // We only support a max of 3 MIDI file types.
425     boolean supported[] = new boolean[3];
426     // The number of supported formats.
427     int count = 0;
428     Iterator<MidiFileWriter> writers =
429       ServiceFactory.lookupProviders(MidiFileWriter.class);
430     while (writers.hasNext())
431     {
432       MidiFileWriter fw = writers.next();
433       int types[] = fw.getMidiFileTypes();
434       for (int i = types.length; i > 0;)
435       {
436         int type = types[--i];
437         if (supported[type] == false)
438         {
439           count++;
440           supported[type] = true;
441         }
442       }
443     }
444     int result[] = new int[count];
445     for (int i = supported.length; i > 0;)
446     {
447       if (supported[--i])
448         result[--count] = i;
449     }
450     return result;
451   }
452
453   /**
454    * Return true if the system supports writing files of type fileType.
455    *
456    * @param fileType the MIDI file type we want to write
457    * @return true if we can write fileType files, false otherwise
458    */
459   public static boolean isFileTypeSupported(int fileType)
460   {
461     Iterator<MidiFileWriter> writers = ServiceFactory.lookupProviders(MidiFileWriter.class);
462     while (writers.hasNext())
463     {
464       MidiFileWriter fw = writers.next();
465
466       if (fw.isFileTypeSupported(fileType))
467         return true;
468     }
469     return false;
470   }
471
472   /**
473    * Return an array of supported MIDI file types on this system
474    * for the given sequnce.
475    *
476    * @param sequence the sequnce to write
477    * @return the array of supported MIDI file types
478    */
479   public static int[] getMidiFileTypes(Sequence sequence)
480   {
481     // We only support a max of 3 MIDI file types.
482     boolean supported[] = new boolean[3];
483     // The number of supported formats.
484     int count = 0;
485     Iterator<MidiFileWriter> writers = ServiceFactory.lookupProviders(MidiFileWriter.class);
486     while (writers.hasNext())
487     {
488       MidiFileWriter fw = (MidiFileWriter) writers.next();
489       int types[] = fw.getMidiFileTypes(sequence);
490       for (int i = types.length; i > 0;)
491       {
492         int type = types[--i];
493         if (supported[type] == false)
494         {
495           count++;
496           supported[type] = true;
497         }
498       }
499     }
500     int result[] = new int[count];
501     for (int i = supported.length; i > 0;)
502     {
503       if (supported[--i])
504         result[--count] = i;
505     }
506     return result;
507   }
508
509   /**
510    * Return true if the system supports writing files of type fileType
511    * for the given sequence.
512    *
513    * @param fileType the MIDI file type we want to write
514    * @param sequence the Sequence we want to write
515    * @return true if we can write fileType files for sequence, false otherwise
516    */
517   public static boolean isFileTypeSupported(int fileType, Sequence sequence)
518   {
519     Iterator<MidiFileWriter> writers = ServiceFactory.lookupProviders(MidiFileWriter.class);
520     while (writers.hasNext())
521     {
522       MidiFileWriter fw = (MidiFileWriter) writers.next();
523
524       if (fw.isFileTypeSupported(fileType, sequence))
525         return true;
526     }
527     return false;
528   }
529
530   /**
531    * Write a sequence to an output stream using a specific MIDI file format.
532    *
533    * @param in the sequence to write
534    * @param fileType the MIDI file format to use
535    * @param out the output stream to write to
536    * @return the number of bytes written
537    * @throws IOException if an I/O exception happens
538    * @throws IllegalArgumentException if fileType is not supported for in
539    */
540   public static int write(Sequence in, int fileType, OutputStream out)
541     throws IOException
542   {
543     Iterator<MidiFileWriter> writers = ServiceFactory.lookupProviders(MidiFileWriter.class);
544     while (writers.hasNext())
545     {
546       MidiFileWriter fw = (MidiFileWriter) writers.next();
547
548       if (fw.isFileTypeSupported(fileType, in))
549         return fw.write(in, fileType, out);
550     }
551     throw new IllegalArgumentException("File type "
552                                        + fileType + " is not supported");
553   }
554
555   /**
556    * Write a sequence to a file using a specific MIDI file format.
557    *
558    * @param in the sequence to write
559    * @param fileType the MIDI file format to use
560    * @param out the file to write to
561    * @return the number of bytes written
562    * @throws IOException if an I/O exception happens
563    * @throws IllegalArgumentException if fileType is not supported for in
564    */
565   public static int write(Sequence in, int fileType, File out)
566     throws IOException
567   {
568     Iterator<MidiFileWriter> writers = ServiceFactory.lookupProviders(MidiFileWriter.class);
569     while (writers.hasNext())
570     {
571       MidiFileWriter fw = (MidiFileWriter) writers.next();
572
573       if (fw.isFileTypeSupported(fileType, in))
574         return fw.write(in, fileType, out);
575     }
576     throw new IllegalArgumentException("File type "
577                                        + fileType + " is not supported");
578   }
579 }