KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > sound > sampled > AudioSystem


1 /*
2  * @(#)AudioSystem.java 1.81 04/07/14
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.sound.sampled;
9
10 import java.io.File JavaDoc;
11 import java.io.InputStream JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.net.URL JavaDoc;
15
16 import java.util.HashSet JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.Vector JavaDoc;
20 import java.util.ArrayList JavaDoc;
21
22 import javax.sound.sampled.spi.AudioFileWriter JavaDoc;
23 import javax.sound.sampled.spi.AudioFileReader JavaDoc;
24 import javax.sound.sampled.spi.FormatConversionProvider JavaDoc;
25 import javax.sound.sampled.spi.MixerProvider JavaDoc;
26
27 import com.sun.media.sound.JDK13Services;
28
29 /* $fb TODO:
30  * - consistent usage of (typed) collections
31  */

32
33
34 /**
35  * The <code>AudioSystem</code> class acts as the entry point to the
36  * sampled-audio system resources. This class lets you query and
37  * access the mixers that are installed on the system.
38  * <code>AudioSystem</code> includes a number of
39  * methods for converting audio data between different formats, and for
40  * translating between audio files and streams. It also provides a method
41  * for obtaining a <code>{@link Line}</code> directly from the
42  * <code>AudioSystem</code> without dealing explicitly
43  * with mixers.
44  *
45  * <p>Properties can be used to specify the default mixer
46  * for specific line types.
47  * Both system properties and a properties file are considered.
48  * In the Sun reference implementation, the properties file is
49  * &quot;lib/sound.properties&quot; in the JRE
50  * directory. If a property exists both as a system property and in the
51  * properties file, the system property takes precedence. If none is
52  * specified, a suitable default is chosen among the available devices.
53  * The syntax of the properties file is specified in
54  * {@link java.util.Properties#load(InputStream) Properties.load}. The
55  * following table lists the available property keys and which methods
56  * consider them:
57  *
58  * <table border=0>
59  * <tr>
60  * <th>Property Key</th>
61  * <th>Interface</th>
62  * <th>Affected Method(s)</th>
63  * </tr>
64  * <tr>
65  * <td><code>javax.sound.sampled.Clip</code></td>
66  * <td>{@link Clip}</td>
67  * <td>{@link #getLine}, {@link #getClip}</td>
68  * </tr>
69  * <tr>
70  * <td><code>javax.sound.sampled.Port</code></td>
71  * <td>{@link Port}</td>
72  * <td>{@link #getLine}</td>
73  * </tr>
74  * <tr>
75  * <td><code>javax.sound.sampled.SourceDataLine</code></td>
76  * <td>{@link SourceDataLine}</td>
77  * <td>{@link #getLine}, {@link #getSourceDataLine}</td>
78  * </tr>
79  * <tr>
80  * <td><code>javax.sound.sampled.TargetDataLine</code></td>
81  * <td>{@link TargetDataLine}</td>
82  * <td>{@link #getLine}, {@link #getTargetDataLine}</td>
83  * </tr>
84  * </table>
85  *
86  * The property value consists of the provider class name
87  * and the mixer name, separated by the hash mark (&quot;#&quot;).
88  * The provider class name is the fully-qualified
89  * name of a concrete {@link javax.sound.sampled.spi.MixerProvider
90  * mixer provider} class. The mixer name is matched against
91  * the <code>String</code> returned by the <code>getName</code>
92  * method of <code>Mixer.Info</code>.
93  * Either the class name, or the mixer name may be omitted.
94  * If only the class name is specified, the trailing hash mark
95  * is optional.
96  *
97  * <p>If the provider class is specified, and it can be
98  * successully retrieved from the installed providers, the list of
99  * <code>Mixer.Info</code> objects is retrieved
100  * from the provider. Otherwise, or when these mixers
101  * do not provide a subsequent match, the list is retrieved
102  * from {@link #getMixerInfo} to contain
103  * all available <code>Mixer.Info</code> objects.
104  *
105  * <p>If a mixer name is specified, the resulting list of
106  * <code>Mixer.Info</code> objects is searched:
107  * the first one with a matching name, and whose
108  * <code>Mixer</code> provides the
109  * respective line interface, will be returned.
110  * If no matching <code>Mixer.Info</code> object
111  * is found, or the mixer name is not specified,
112  * the first mixer from the resulting
113  * list, which provides the respective line
114  * interface, will be returned.
115  *
116  * For example, the property <code>javax.sound.sampled.Clip</code>
117  * with a value
118  * <code>&quot;com.sun.media.sound.MixerProvider#SunClip&quot;</code>
119  * will have the following consequences when
120  * <code>getLine</code> is called requesting a <code>Clip</code>
121  * instance:
122  * if the class <code>com.sun.media.sound.MixerProvider</code> exists
123  * in the list of installed mixer providers,
124  * the first <code>Clip</code> from the first mixer with name
125  * <code>&quot;SunClip&quot;</code> will be returned. If it cannot
126  * be found, the first <code>Clip</code> from the first mixer
127  * of the specified provider will be returned, regardless of name.
128  * If there is none, the first <code>Clip</code> from the first
129  * <code>Mixer</code> with name
130  * <code>&quot;SunClip&quot;</code> in the list of all mixers
131  * (as returned by <code>getMixerInfo</code>) will be returned,
132  * or, if not found, the first <code>Clip</code> of the first
133  * <code>Mixer</code>that can be found in the list of all
134  * mixers is returned.
135  * If that fails, too, an <code>IllegalArgumentException</code>
136  * is thrown.
137  *
138  * @author Kara Kytle
139  * @author Florian Bomers
140  * @author Matthias Pfisterer
141  * @author Kevin P. Smith
142  * @version 1.81, 04/07/14
143  *
144  * @see AudioFormat
145  * @see AudioInputStream
146  * @see Mixer
147  * @see Line
148  * @see Line.Info
149  * @since 1.3
150  */

151 public class AudioSystem {
152
153     /**
154      * An integer that stands for an unknown numeric value.
155      * This value is appropriate only for signed quantities that do not
156      * normally take negative values. Examples include file sizes, frame
157      * sizes, buffer sizes, and sample rates.
158      * A number of Java Sound constructors accept
159      * a value of <code>NOT_SPECIFIED</code> for such parameters. Other
160      * methods may also accept or return this value, as documented.
161      */

162     public static final int NOT_SPECIFIED = -1;
163
164     /**
165      * Private no-args constructor for ensuring against instantiation.
166      */

167     private AudioSystem() {
168     }
169
170
171     /**
172      * Obtains an array of mixer info objects that represents
173      * the set of audio mixers that are currently installed on the system.
174      * @return an array of info objects for the currently installed mixers. If no mixers
175      * are available on the system, an array of length 0 is returned.
176      * @see #getMixer
177      */

178     public static Mixer.Info JavaDoc[] getMixerInfo() {
179
180     List JavaDoc infos = getMixerInfoList();
181     Mixer.Info JavaDoc[] allInfos = (Mixer.Info JavaDoc[]) infos.toArray(new Mixer.Info JavaDoc[infos.size()]);
182     return allInfos;
183     }
184
185
186     /**
187      * Obtains the requested audio mixer.
188      * @param info a <code>Mixer.Info</code> object representing the desired
189      * mixer, or <code>null</code> for the system default mixer
190      * @return the requested mixer
191      * @throws SecurityException if the requested mixer
192      * is unavailable because of security restrictions
193      * @throws IllegalArgumentException if the info object does not represent
194      * a mixer installed on the system
195      * @see #getMixerInfo
196      */

197     public static Mixer JavaDoc getMixer(Mixer.Info JavaDoc info) {
198
199     Mixer JavaDoc mixer = null;
200     List JavaDoc providers = getMixerProviders();
201
202     for(int i = 0; i < providers.size(); i++ ) {
203
204         try {
205         return ((MixerProvider JavaDoc)providers.get(i)).getMixer(info);
206
207         } catch (IllegalArgumentException JavaDoc e) {
208         } catch (NullPointerException JavaDoc e) {
209         // $$jb 08.20.99: If the strings in the info object aren't
210
// set, then Netscape (using jdk1.1.5) tends to throw
211
// NPE's when doing some string manipulation. This is
212
// probably not the best fix, but is solves the problem
213
// of the NPE in Netscape using local classes
214
// $$jb 11.01.99: Replacing this patch.
215
}
216     }
217
218     //$$fb if looking for default mixer, and not found yet, add a round of looking
219
if (info == null) {
220         for(int i = 0; i < providers.size(); i++ ) {
221         try {
222             MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
223             Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
224             // start from 0 to last device (do not reverse this order)
225
for (int ii = 0; ii < infos.length; ii++) {
226             try {
227                 return provider.getMixer(infos[ii]);
228             } catch (IllegalArgumentException JavaDoc e) {
229                 // this is not a good default device :)
230
}
231             }
232         } catch (IllegalArgumentException JavaDoc e) {
233         } catch (NullPointerException JavaDoc e) {
234         }
235         }
236     }
237
238
239     throw new IllegalArgumentException JavaDoc("Mixer not supported: "
240                        + (info!=null?info.toString():"null"));
241     }
242
243
244     //$$fb 2002-11-26: fix for 4757930: DOC: AudioSystem.getTarget/SourceLineInfo() is ambiguous
245
/**
246      * Obtains information about all source lines of a particular type that are supported
247      * by the installed mixers.
248      * @param info a <code>Line.Info</code> object that specifies the kind of
249      * lines about which information is requested
250      * @return an array of <code>Line.Info</code> objects describing source lines matching
251      * the type requested. If no matching source lines are supported, an array of length 0
252      * is returned.
253      *
254      * @see Mixer#getSourceLineInfo(Line.Info)
255      */

256     public static Line.Info JavaDoc[] getSourceLineInfo(Line.Info JavaDoc info) {
257
258     Vector JavaDoc vector = new Vector JavaDoc();
259     Line.Info JavaDoc[] currentInfoArray;
260
261     Mixer JavaDoc mixer;
262     Line.Info JavaDoc fullInfo = null;
263     Mixer.Info JavaDoc[] infoArray = getMixerInfo();
264
265     for (int i = 0; i < infoArray.length; i++) {
266
267         mixer = getMixer(infoArray[i]);
268
269         currentInfoArray = mixer.getSourceLineInfo(info);
270         for (int j = 0; j < currentInfoArray.length; j++) {
271         vector.addElement(currentInfoArray[j]);
272         }
273     }
274
275     Line.Info JavaDoc[] returnedArray = new Line.Info JavaDoc[vector.size()];
276
277     for (int i = 0; i < returnedArray.length; i++) {
278         returnedArray[i] = (Line.Info JavaDoc)vector.get(i);
279     }
280
281     return returnedArray;
282     }
283
284
285     /**
286      * Obtains information about all target lines of a particular type that are supported
287      * by the installed mixers.
288      * @param info a <code>Line.Info</code> object that specifies the kind of
289      * lines about which information is requested
290      * @return an array of <code>Line.Info</code> objects describing target lines matching
291      * the type requested. If no matching target lines are supported, an array of length 0
292      * is returned.
293      *
294      * @see Mixer#getTargetLineInfo(Line.Info)
295      */

296     public static Line.Info JavaDoc[] getTargetLineInfo(Line.Info JavaDoc info) {
297
298     Vector JavaDoc vector = new Vector JavaDoc();
299     Line.Info JavaDoc[] currentInfoArray;
300
301     Mixer JavaDoc mixer;
302     Line.Info JavaDoc fullInfo = null;
303     Mixer.Info JavaDoc[] infoArray = getMixerInfo();
304
305     for (int i = 0; i < infoArray.length; i++) {
306
307         mixer = getMixer(infoArray[i]);
308
309         currentInfoArray = mixer.getTargetLineInfo(info);
310         for (int j = 0; j < currentInfoArray.length; j++) {
311         vector.addElement(currentInfoArray[j]);
312         }
313     }
314
315     Line.Info JavaDoc[] returnedArray = new Line.Info JavaDoc[vector.size()];
316
317     for (int i = 0; i < returnedArray.length; i++) {
318         returnedArray[i] = (Line.Info JavaDoc)vector.get(i);
319     }
320
321     return returnedArray;
322     }
323
324
325     /**
326      * Indicates whether the system supports any lines that match
327      * the specified <code>Line.Info</code> object. A line is supported if
328      * any installed mixer supports it.
329      * @param info a <code>Line.Info</code> object describing the line for which support is queried
330      * @return <code>true</code> if at least one matching line is
331      * supported, otherwise <code>false</code>
332      *
333      * @see Mixer#isLineSupported(Line.Info)
334      */

335     public static boolean isLineSupported(Line.Info JavaDoc info) {
336
337     Mixer JavaDoc mixer;
338     Mixer.Info JavaDoc[] infoArray = getMixerInfo();
339
340     for (int i = 0; i < infoArray.length; i++) {
341
342         if( infoArray[i] != null ) {
343         mixer = getMixer(infoArray[i]);
344         if (mixer.isLineSupported(info)) {
345             return true;
346         }
347         }
348     }
349
350     return false;
351     }
352
353     /**
354      * Obtains a line that matches the description in the specified
355      * <code>Line.Info</code> object.
356      *
357      * <p>If a <code>DataLine</code> is requested, and <code>info</code>
358      * is an instance of <code>DataLine.Info</code> specifying at least
359      * one fully qualified audio format, the last one
360      * will be used as the default format of the returned
361      * <code>DataLine</code>.
362      *
363      * <p>If system properties
364      * <code>javax.sound.sampled.Clip</code>,
365      * <code>javax.sound.sampled.Port</code>,
366      * <code>javax.sound.sampled.SourceDataLine</code> and
367      * <code>javax.sound.sampled.TargetDataLine</code> are defined
368      * or they are defined in the file &quot;sound.properties&quot;,
369      * they are used to retrieve default lines.
370      * For details, refer to the {@link AudioSystem class description}.
371      *
372      * If the respective property is not set, or the mixer
373      * requested in the property is not installed or does not provide the
374      * requested line, all installed mixers are queried for the
375      * requested line type. A Line will be returned from the first mixer
376      * providing the requested line type.
377      *
378      * @param info a <code>Line.Info</code> object describing the desired kind of line
379      * @return a line of the requested kind
380      *
381      * @throws LineUnavailableException if a matching line
382      * is not available due to resource restrictions
383      * @throws SecurityException if a matching line
384      * is not available due to security restrictions
385      * @throws IllegalArgumentException if the system does not
386      * support at least one line matching the specified
387      * <code>Line.Info</code> object
388      * through any installed mixer
389      */

390     public static Line JavaDoc getLine(Line.Info JavaDoc info) throws LineUnavailableException JavaDoc {
391     LineUnavailableException JavaDoc lue = null;
392     List JavaDoc providers = getMixerProviders();
393
394
395     // 1: try from default mixer for this line class
396
try {
397         Mixer JavaDoc mixer = getDefaultMixer(providers, info);
398         if (mixer != null && mixer.isLineSupported(info)) {
399         return mixer.getLine(info);
400         }
401     } catch (LineUnavailableException JavaDoc e) {
402         lue = e;
403     } catch (IllegalArgumentException JavaDoc iae) {
404         // must not happen... but better to catch it here,
405
// if plug-ins are badly written
406
}
407
408
409     // 2: if that doesn't work, try to find any mixing mixer
410
for(int i = 0; i < providers.size(); i++) {
411         MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
412         Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
413
414         for (int j = 0; j < infos.length; j++) {
415         try {
416             Mixer JavaDoc mixer = provider.getMixer(infos[j]);
417             // see if this is an appropriate mixer which can mix
418
if (isAppropriateMixer(mixer, info, true)) {
419             return mixer.getLine(info);
420             }
421         } catch (LineUnavailableException JavaDoc e) {
422             lue = e;
423         } catch (IllegalArgumentException JavaDoc iae) {
424             // must not happen... but better to catch it here,
425
// if plug-ins are badly written
426
}
427         }
428     }
429
430
431     // 3: if that didn't work, try to find any non-mixing mixer
432
for(int i = 0; i < providers.size(); i++) {
433         MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
434         Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
435         for (int j = 0; j < infos.length; j++) {
436         try {
437             Mixer JavaDoc mixer = provider.getMixer(infos[j]);
438             // see if this is an appropriate mixer which can mix
439
if (isAppropriateMixer(mixer, info, false)) {
440             return mixer.getLine(info);
441             }
442         } catch (LineUnavailableException JavaDoc e) {
443             lue = e;
444         } catch (IllegalArgumentException JavaDoc iae) {
445             // must not happen... but better to catch it here,
446
// if plug-ins are badly written
447
}
448         }
449     }
450
451     // if this line was supported but was not available, throw the last
452
// LineUnavailableException we got (??).
453
if (lue != null) {
454         throw lue;
455     }
456
457     // otherwise, the requested line was not supported, so throw
458
// an Illegal argument exception
459
throw new IllegalArgumentException JavaDoc("No line matching " +
460                        info.toString() + " is supported.");
461     }
462
463
464     /**
465      * Obtains a clip that can be used for playing back
466      * an audio file or an audio stream. The returned clip
467      * will be provided by the default system mixer, or,
468      * if not possible, by any other mixer installed in the
469      * system that supports a <code>Clip</code>
470      * object.
471      *
472      * <p>The returned clip must be opened with the
473      * <code>open(AudioFormat)</code> or
474      * <code>open(AudioInputStream)</code> method.
475      *
476      * <p>This is a high-level method that uses <code>getMixer</code>
477      * and <getLine</code> internally.
478      *
479      * <p>If the system property
480      * <code>javax.sound.sampled.Clip</code>
481      * is defined or it is defined in the file &quot;sound.properties&quot;,
482      * it is used to retrieve the default clip.
483      * For details, refer to the {@link AudioSystem class description}.
484      *
485      * @return the desired clip object
486      *
487      * @throws LineUnavailableException if a clip object
488      * is not available due to resource restrictions
489      * @throws SecurityException if a clip object
490      * is not available due to security restrictions
491      * @throws IllegalArgumentException if the system does not
492      * support at least one clip instance through any installed mixer
493      *
494      * @see #getClip(Mixer.Info)
495      * @since 1.5
496      */

497     public static Clip JavaDoc getClip() throws LineUnavailableException JavaDoc{
498     AudioFormat JavaDoc format = new AudioFormat JavaDoc(AudioFormat.Encoding.PCM_SIGNED,
499                          AudioSystem.NOT_SPECIFIED,
500                          16, 2, 4,
501                          AudioSystem.NOT_SPECIFIED, true);
502     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(Clip JavaDoc.class, format);
503     return (Clip JavaDoc) AudioSystem.getLine(info);
504     }
505
506
507     /**
508      * Obtains a clip from the specified mixer that can be
509      * used for playing back an audio file or an audio stream.
510      *
511      * <p>The returned clip must be opened with the
512      * <code>open(AudioFormat)</code> or
513      * <code>open(AudioInputStream)</code> method.
514      *
515      * <p>This is a high-level method that uses <code>getMixer</code>
516      * and <getLine</code> internally.
517      *
518      * @param mixerInfo a <code>Mixer.Info</code> object representing the
519      * desired mixer, or <code>null</code> for the system default mixer
520      * @return a clip object from the specified mixer
521      *
522      * @throws LineUnavailableException if a clip
523      * is not available from this mixer due to resource restrictions
524      * @throws SecurityException if a clip
525      * is not available from this mixer due to security restrictions
526      * @throws IllegalArgumentException if the system does not
527      * support at least one clip through the specified mixer
528      *
529      * @see #getClip()
530      * @since 1.5
531      */

532     public static Clip JavaDoc getClip(Mixer.Info JavaDoc mixerInfo) throws LineUnavailableException JavaDoc{
533     AudioFormat JavaDoc format = new AudioFormat JavaDoc(AudioFormat.Encoding.PCM_SIGNED,
534                          AudioSystem.NOT_SPECIFIED,
535                          16, 2, 4,
536                          AudioSystem.NOT_SPECIFIED, true);
537     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(Clip JavaDoc.class, format);
538     Mixer JavaDoc mixer = AudioSystem.getMixer(mixerInfo);
539     return (Clip JavaDoc) mixer.getLine(info);
540     }
541
542
543     /**
544      * Obtains a source data line that can be used for playing back
545      * audio data in the format specified by the
546      * <code>AudioFormat</code> object. The returned line
547      * will be provided by the default system mixer, or,
548      * if not possible, by any other mixer installed in the
549      * system that supports a matching
550      * <code>SourceDataLine</code> object.
551      *
552      * <p>The returned line should be opened with the
553      * <code>open(AudioFormat)</code> or
554      * <code>open(AudioFormat, int)</code> method.
555      *
556      * <p>This is a high-level method that uses <code>getMixer</code>
557      * and <getLine</code> internally.
558      *
559      * <p>The returned <code>SourceDataLine</code>'s default
560      * audio format will be initialized with <code>format</code>.
561      *
562      * <p>If the system property
563      * <code>javax.sound.sampled.SourceDataLine</code>
564      * is defined or it is defined in the file &quot;sound.properties&quot;,
565      * it is used to retrieve the default source data line.
566      * For details, refer to the {@link AudioSystem class description}.
567      *
568      * @param format an <code>AudioFormat</code> object specifying
569      * the supported audio format of the returned line,
570      * or <code>null</code> for any audio format
571      * @return the desired <code>SourceDataLine</code> object
572      *
573      * @throws LineUnavailableException if a matching source data line
574      * is not available due to resource restrictions
575      * @throws SecurityException if a matching source data line
576      * is not available due to security restrictions
577      * @throws IllegalArgumentException if the system does not
578      * support at least one source data line supporting the
579      * specified audio format through any installed mixer
580      *
581      * @see #getSourceDataLine(AudioFormat, Mixer.Info)
582      * @since 1.5
583      */

584     public static SourceDataLine JavaDoc getSourceDataLine(AudioFormat JavaDoc format)
585         throws LineUnavailableException JavaDoc{
586     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(SourceDataLine JavaDoc.class, format);
587     return (SourceDataLine JavaDoc) AudioSystem.getLine(info);
588     }
589
590
591     /**
592      * Obtains a source data line that can be used for playing back
593      * audio data in the format specified by the
594      * <code>AudioFormat</code> object, provided by the mixer
595      * specified by the <code>Mixer.Info</code> object.
596      *
597      * <p>The returned line should be opened with the
598      * <code>open(AudioFormat)</code> or
599      * <code>open(AudioFormat, int)</code> method.
600      *
601      * <p>This is a high-level method that uses <code>getMixer</code>
602      * and <getLine</code> internally.
603      *
604      * <p>The returned <code>SourceDataLine</code>'s default
605      * audio format will be initialized with <code>format</code>.
606      *
607      * @param format an <code>AudioFormat</code> object specifying
608      * the supported audio format of the returned line,
609      * or <code>null</code> for any audio format
610      * @param mixerinfo a <code>Mixer.Info</code> object representing
611      * the desired mixer, or <code>null</code> for the system
612      * default mixer
613      * @return the desired <code>SourceDataLine</code> object
614      *
615      * @throws LineUnavailableException if a matching source data
616      * line is not available from the specified mixer due
617      * to resource restrictions
618      * @throws SecurityException if a matching source data line
619      * is not available from the specified mixer due to
620      * security restrictions
621      * @throws IllegalArgumentException if the specified mixer does
622      * not support at least one source data line supporting
623      * the specified audio format
624      *
625      * @see #getSourceDataLine(AudioFormat)
626      * @since 1.5
627      */

628     public static SourceDataLine JavaDoc getSourceDataLine(AudioFormat JavaDoc format,
629                            Mixer.Info JavaDoc mixerinfo)
630         throws LineUnavailableException JavaDoc{
631     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(SourceDataLine JavaDoc.class, format);
632     Mixer JavaDoc mixer = AudioSystem.getMixer(mixerinfo);
633     return (SourceDataLine JavaDoc) mixer.getLine(info);
634   }
635
636
637     /**
638      * Obtains a target data line that can be used for recording
639      * audio data in the format specified by the
640      * <code>AudioFormat</code> object. The returned line
641      * will be provided by the default system mixer, or,
642      * if not possible, by any other mixer installed in the
643      * system that supports a matching
644      * <code>TargetDataLine</code> object.
645      *
646      * <p>The returned line should be opened with the
647      * <code>open(AudioFormat)</code> or
648      * <code>open(AudioFormat, int)</code> method.
649      *
650      * <p>This is a high-level method that uses <code>getMixer</code>
651      * and <getLine</code> internally.
652      *
653      * <p>The returned <code>TargetDataLine</code>'s default
654      * audio format will be initialized with <code>format</code>.
655      *
656      * @param format an <code>AudioFormat</code> object specifying
657      * the supported audio format of the returned line,
658      * or <code>null</code> for any audio format
659      * @return the desired <code>TargetDataLine</code> object
660      *
661      * @throws LineUnavailableException if a matching target data line
662      * is not available due to resource restrictions
663      * @throws SecurityException if a matching target data line
664      * is not available due to security restrictions
665      * @throws IllegalArgumentException if the system does not
666      * support at least one target data line supporting the
667      * specified audio format through any installed mixer
668      *
669      * @see #getTargetDataLine(AudioFormat, Mixer.Info)
670      * @see AudioPermission
671      * @since 1.5
672      */

673     public static TargetDataLine JavaDoc getTargetDataLine(AudioFormat JavaDoc format)
674     throws LineUnavailableException JavaDoc{
675
676     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(TargetDataLine JavaDoc.class, format);
677     return (TargetDataLine JavaDoc) AudioSystem.getLine(info);
678     }
679
680
681
682     /**
683      * Obtains a target data line that can be used for recording
684      * audio data in the format specified by the
685      * <code>AudioFormat</code> object, provided by the mixer
686      * specified by the <code>Mixer.Info</code> object.
687      *
688      * <p>The returned line should be opened with the
689      * <code>open(AudioFormat)</code> or
690      * <code>open(AudioFormat, int)</code> method.
691      *
692      * <p>This is a high-level method that uses <code>getMixer</code>
693      * and <getLine</code> internally.
694      *
695      * <p>The returned <code>TargetDataLine</code>'s default
696      * audio format will be initialized with <code>format</code>.
697      *
698      * <p>If the system property
699      * <code>javax.sound.sampled.TargetDataLine</code>
700      * is defined or it is defined in the file &quot;sound.properties&quot;,
701      * it is used to retrieve the default target data line.
702      * For details, refer to the {@link AudioSystem class description}.
703      *
704      * @param format an <code>AudioFormat</code> object specifying
705      * the supported audio format of the returned line,
706      * or <code>null</code> for any audio format
707      * @param mixerinfo a <code>Mixer.Info</code> object representing the
708      * desired mixer, or <code>null</code> for the system default mixer
709      * @return the desired <code>TargetDataLine</code> object
710      *
711      * @throws LineUnavailableException if a matching target data
712      * line is not available from the specified mixer due
713      * to resource restrictions
714      * @throws SecurityException if a matching target data line
715      * is not available from the specified mixer due to
716      * security restrictions
717      * @throws IllegalArgumentException if the specified mixer does
718      * not support at least one target data line supporting
719      * the specified audio format
720      *
721      * @see #getTargetDataLine(AudioFormat)
722      * @see AudioPermission
723      * @since 1.5
724      */

725     public static TargetDataLine JavaDoc getTargetDataLine(AudioFormat JavaDoc format,
726                            Mixer.Info JavaDoc mixerinfo)
727     throws LineUnavailableException JavaDoc {
728
729     DataLine.Info JavaDoc info = new DataLine.Info JavaDoc(TargetDataLine JavaDoc.class, format);
730     Mixer JavaDoc mixer = AudioSystem.getMixer(mixerinfo);
731     return (TargetDataLine JavaDoc) mixer.getLine(info);
732     }
733
734
735     // $$fb 2002-04-12: fix for 4662082: behavior of AudioSystem.getTargetEncodings() methods doesn't match the spec
736
/**
737      * Obtains the encodings that the system can obtain from an
738      * audio input stream with the specified encoding using the set
739      * of installed format converters.
740      * @param sourceEncoding the encoding for which conversion support
741      * is queried
742      * @return array of encodings. If <code>sourceEncoding</code>is not supported,
743      * an array of length 0 is returned. Otherwise, the array will have a length
744      * of at least 1, representing <code>sourceEncoding</code> (no conversion).
745      */

746     public static AudioFormat.Encoding JavaDoc[] getTargetEncodings(AudioFormat.Encoding JavaDoc sourceEncoding) {
747
748     List JavaDoc codecs = getFormatConversionProviders();
749     Vector JavaDoc encodings = new Vector JavaDoc();
750
751     AudioFormat.Encoding JavaDoc encs[] = null;
752
753     // gather from all the codecs
754
for(int i=0; i<codecs.size(); i++ ) {
755         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
756         if( codec.isSourceEncodingSupported( sourceEncoding ) ) {
757         encs = codec.getTargetEncodings();
758         for (int j = 0; j < encs.length; j++) {
759             encodings.addElement( encs[j] );
760         }
761         }
762     }
763     AudioFormat.Encoding JavaDoc encs2[] = (AudioFormat.Encoding JavaDoc[]) encodings.toArray(new AudioFormat.Encoding JavaDoc[0]);
764     return encs2;
765     }
766
767
768
769     // $$fb 2002-04-12: fix for 4662082: behavior of AudioSystem.getTargetEncodings() methods doesn't match the spec
770
/**
771      * Obtains the encodings that the system can obtain from an
772      * audio input stream with the specified format using the set
773      * of installed format converters.
774      * @param sourceFormat the audio format for which conversion
775      * is queried
776      * @return array of encodings. If <code>sourceFormat</code>is not supported,
777      * an array of length 0 is returned. Otherwise, the array will have a length
778      * of at least 1, representing the encoding of <code>sourceFormat</code> (no conversion).
779      */

780     public static AudioFormat.Encoding JavaDoc[] getTargetEncodings(AudioFormat JavaDoc sourceFormat) {
781
782
783     List JavaDoc codecs = getFormatConversionProviders();
784     Vector JavaDoc encodings = new Vector JavaDoc();
785
786     int size = 0;
787     int index = 0;
788     AudioFormat.Encoding JavaDoc encs[] = null;
789
790     // gather from all the codecs
791

792     for(int i=0; i<codecs.size(); i++ ) {
793         encs = ((FormatConversionProvider JavaDoc) codecs.get(i)).getTargetEncodings(sourceFormat);
794         size += encs.length;
795         encodings.addElement( encs );
796     }
797
798     // now build a new array
799

800     AudioFormat.Encoding JavaDoc encs2[] = new AudioFormat.Encoding JavaDoc[size];
801     for(int i=0; i<encodings.size(); i++ ) {
802         encs = (AudioFormat.Encoding JavaDoc [])(encodings.get(i));
803         for(int j=0; j<encs.length; j++ ) {
804         encs2[index++] = encs[j];
805         }
806     }
807     return encs2;
808     }
809
810
811     /**
812      * Indicates whether an audio input stream of the specified encoding
813      * can be obtained from an audio input stream that has the specified
814      * format.
815      * @param targetEncoding the desired encoding after conversion
816      * @param sourceFormat the audio format before conversion
817      * @return <code>true</code> if the conversion is supported,
818      * otherwise <code>false</code>
819      */

820     public static boolean isConversionSupported(AudioFormat.Encoding JavaDoc targetEncoding, AudioFormat JavaDoc sourceFormat) {
821
822
823     List JavaDoc codecs = getFormatConversionProviders();
824
825     for(int i=0; i<codecs.size(); i++ ) {
826         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
827         if(codec.isConversionSupported(targetEncoding,sourceFormat) ) {
828         return true;
829         }
830     }
831     return false;
832     }
833
834
835     /**
836      * Obtains an audio input stream of the indicated encoding, by converting the
837      * provided audio input stream.
838      * @param targetEncoding the desired encoding after conversion
839      * @param sourceStream the stream to be converted
840      * @return an audio input stream of the indicated encoding
841      * @throws IllegalArgumentException if the conversion is not supported
842      * @see #getTargetEncodings(AudioFormat.Encoding)
843      * @see #getTargetEncodings(AudioFormat)
844      * @see #isConversionSupported(AudioFormat.Encoding, AudioFormat)
845      * @see #getAudioInputStream(AudioFormat, AudioInputStream)
846      */

847     public static AudioInputStream JavaDoc getAudioInputStream(AudioFormat.Encoding JavaDoc targetEncoding,
848                                AudioInputStream JavaDoc sourceStream) {
849
850     List JavaDoc codecs = getFormatConversionProviders();
851
852     for(int i = 0; i < codecs.size(); i++) {
853         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
854         if( codec.isConversionSupported( targetEncoding, sourceStream.getFormat() ) ) {
855         return codec.getAudioInputStream( targetEncoding, sourceStream );
856         }
857     }
858     // we ran out of options, throw an exception
859
throw new IllegalArgumentException JavaDoc("Unsupported conversion: " + targetEncoding + " from " + sourceStream.getFormat());
860     }
861
862
863     /**
864      * Obtains the formats that have a particular encoding and that the system can
865      * obtain from a stream of the specified format using the set of
866      * installed format converters.
867      * @param targetEncoding the desired encoding after conversion
868      * @param sourceFormat the audio format before conversion
869      * @return array of formats. If no formats of the specified
870      * encoding are supported, an array of length 0 is returned.
871      */

872     public static AudioFormat JavaDoc[] getTargetFormats(AudioFormat.Encoding JavaDoc targetEncoding, AudioFormat JavaDoc sourceFormat) {
873
874     List JavaDoc codecs = getFormatConversionProviders();
875     Vector JavaDoc formats = new Vector JavaDoc();
876
877     int size = 0;
878     int index = 0;
879     AudioFormat JavaDoc fmts[] = null;
880
881     // gather from all the codecs
882

883     for(int i=0; i<codecs.size(); i++ ) {
884         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
885         fmts = codec.getTargetFormats(targetEncoding, sourceFormat);
886         size += fmts.length;
887         formats.addElement( fmts );
888     }
889
890     // now build a new array
891

892     AudioFormat JavaDoc fmts2[] = new AudioFormat JavaDoc[size];
893     for(int i=0; i<formats.size(); i++ ) {
894         fmts = (AudioFormat JavaDoc [])(formats.get(i));
895         for(int j=0; j<fmts.length; j++ ) {
896         fmts2[index++] = fmts[j];
897         }
898     }
899     return fmts2;
900     }
901
902
903     /**
904      * Indicates whether an audio input stream of a specified format
905      * can be obtained from an audio input stream of another specified format.
906      * @param targetFormat the desired audio format after conversion
907      * @param sourceFormat the audio format before conversion
908      * @return <code>true</code> if the conversion is supported,
909      * otherwise <code>false</code>
910      */

911
912     public static boolean isConversionSupported(AudioFormat JavaDoc targetFormat, AudioFormat JavaDoc sourceFormat) {
913
914     List JavaDoc codecs = getFormatConversionProviders();
915
916     for(int i=0; i<codecs.size(); i++ ) {
917         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
918         if(codec.isConversionSupported(targetFormat, sourceFormat) ) {
919         return true;
920         }
921     }
922     return false;
923     }
924
925
926     /**
927      * Obtains an audio input stream of the indicated format, by converting the
928      * provided audio input stream.
929      * @param targetFormat the desired audio format after conversion
930      * @param sourceStream the stream to be converted
931      * @return an audio input stream of the indicated format
932      * @throws IllegalArgumentException if the conversion is not supported
933      * #see #getTargetEncodings(AudioFormat)
934      * @see #getTargetFormats(AudioFormat.Encoding, AudioFormat)
935      * @see #isConversionSupported(AudioFormat, AudioFormat)
936      * @see #getAudioInputStream(AudioFormat.Encoding, AudioInputStream)
937      */

938     public static AudioInputStream JavaDoc getAudioInputStream(AudioFormat JavaDoc targetFormat,
939                                AudioInputStream JavaDoc sourceStream) {
940
941     if (sourceStream.getFormat().matches(targetFormat)) {
942         return sourceStream;
943     }
944
945     List JavaDoc codecs = getFormatConversionProviders();
946
947     for(int i = 0; i < codecs.size(); i++) {
948         FormatConversionProvider JavaDoc codec = (FormatConversionProvider JavaDoc) codecs.get(i);
949         if(codec.isConversionSupported(targetFormat,sourceStream.getFormat()) ) {
950         return codec.getAudioInputStream(targetFormat,sourceStream);
951         }
952     }
953
954     // we ran out of options...
955
throw new IllegalArgumentException JavaDoc("Unsupported conversion: " + targetFormat + " from " + sourceStream.getFormat());
956     }
957
958
959     /**
960      * Obtains the audio file format of the provided input stream. The stream must
961      * point to valid audio file data. The implementation of this method may require
962      * multiple parsers to examine the stream to determine whether they support it.
963      * These parsers must be able to mark the stream, read enough data to determine whether they
964      * support the stream, and, if not, reset the stream's read pointer to its original
965      * position. If the input stream does not support these operations, this method may fail
966      * with an <code>IOException</code>.
967      * @param stream the input stream from which file format information should be
968      * extracted
969      * @return an <code>AudioFileFormat</code> object describing the stream's audio file format
970      * @throws UnsupportedAudioFileException if the stream does not point to valid audio
971      * file data recognized by the system
972      * @throws IOException if an input/output exception occurs
973      * @see InputStream#markSupported
974      * @see InputStream#mark
975      */

976     public static AudioFileFormat JavaDoc getAudioFileFormat(InputStream JavaDoc stream)
977     throws UnsupportedAudioFileException JavaDoc, IOException JavaDoc {
978
979     List JavaDoc providers = getAudioFileReaders();
980     AudioFileFormat JavaDoc format = null;
981
982     for(int i = 0; i < providers.size(); i++ ) {
983         AudioFileReader JavaDoc reader = (AudioFileReader JavaDoc) providers.get(i);
984         try {
985         format = reader.getAudioFileFormat( stream ); // throws IOException
986
break;
987         } catch (UnsupportedAudioFileException JavaDoc e) {
988         continue;
989         }
990     }
991
992     if( format==null ) {
993         throw new UnsupportedAudioFileException JavaDoc("file is not a supported file type");
994     } else {
995         return format;
996     }
997     }
998
999     /**
1000     * Obtains the audio file format of the specified URL. The URL must
1001     * point to valid audio file data.
1002     * @param url the URL from which file format information should be
1003     * extracted
1004     * @return an <code>AudioFileFormat</code> object describing the audio file format
1005     * @throws UnsupportedAudioFileException if the URL does not point to valid audio
1006     * file data recognized by the system
1007     * @throws IOException if an input/output exception occurs
1008     */

1009    public static AudioFileFormat JavaDoc getAudioFileFormat(URL JavaDoc url)
1010    throws UnsupportedAudioFileException JavaDoc, IOException JavaDoc {
1011
1012    List JavaDoc providers = getAudioFileReaders();
1013    AudioFileFormat JavaDoc format = null;
1014
1015    for(int i = 0; i < providers.size(); i++ ) {
1016        AudioFileReader JavaDoc reader = (AudioFileReader JavaDoc) providers.get(i);
1017        try {
1018        format = reader.getAudioFileFormat( url ); // throws IOException
1019
break;
1020        } catch (UnsupportedAudioFileException JavaDoc e) {
1021        continue;
1022        }
1023    }
1024
1025    if( format==null ) {
1026        throw new UnsupportedAudioFileException JavaDoc("file is not a supported file type");
1027    } else {
1028        return format;
1029    }
1030    }
1031
1032    /**
1033     * Obtains the audio file format of the specified <code>File</code>. The <code>File</code> must
1034     * point to valid audio file data.
1035     * @param file the <code>File</code> from which file format information should be
1036     * extracted
1037     * @return an <code>AudioFileFormat</code> object describing the audio file format
1038     * @throws UnsupportedAudioFileException if the <code>File</code> does not point to valid audio
1039     * file data recognized by the system
1040     * @throws IOException if an I/O exception occurs
1041     */

1042    public static AudioFileFormat JavaDoc getAudioFileFormat(File JavaDoc file)
1043    throws UnsupportedAudioFileException JavaDoc, IOException JavaDoc {
1044
1045    List JavaDoc providers = getAudioFileReaders();
1046    AudioFileFormat JavaDoc format = null;
1047
1048    for(int i = 0; i < providers.size(); i++ ) {
1049        AudioFileReader JavaDoc reader = (AudioFileReader JavaDoc) providers.get(i);
1050        try {
1051        format = reader.getAudioFileFormat( file ); // throws IOException
1052
break;
1053        } catch (UnsupportedAudioFileException JavaDoc e) {
1054        continue;
1055        }
1056    }
1057
1058    if( format==null ) {
1059        throw new UnsupportedAudioFileException JavaDoc("file is not a supported file type");
1060    } else {
1061        return format;
1062    }
1063    }
1064
1065
1066    /**
1067     * Obtains an audio input stream from the provided input stream. The stream must
1068     * point to valid audio file data. The implementation of this method may
1069     * require multiple parsers to
1070     * examine the stream to determine whether they support it. These parsers must
1071     * be able to mark the stream, read enough data to determine whether they
1072     * support the stream, and, if not, reset the stream's read pointer to its original
1073     * position. If the input stream does not support these operation, this method may fail
1074     * with an <code>IOException</code>.
1075     * @param stream the input stream from which the <code>AudioInputStream</code> should be
1076     * constructed
1077     * @return an <code>AudioInputStream</code> object based on the audio file data contained
1078     * in the input stream.
1079     * @throws UnsupportedAudioFileException if the stream does not point to valid audio
1080     * file data recognized by the system
1081     * @throws IOException if an I/O exception occurs
1082     * @see InputStream#markSupported
1083     * @see InputStream#mark
1084     */

1085    public static AudioInputStream JavaDoc getAudioInputStream(InputStream JavaDoc stream)
1086    throws UnsupportedAudioFileException JavaDoc, IOException JavaDoc {
1087
1088    List JavaDoc providers = getAudioFileReaders();
1089    AudioInputStream JavaDoc audioStream = null;
1090
1091    for(int i = 0; i < providers.size(); i++ ) {
1092        AudioFileReader JavaDoc reader = (AudioFileReader JavaDoc) providers.get(i);
1093        try {
1094        audioStream = reader.getAudioInputStream( stream ); // throws IOException
1095
break;
1096        } catch (UnsupportedAudioFileException JavaDoc e) {
1097        continue;
1098        }
1099    }
1100
1101    if( audioStream==null ) {
1102        throw new UnsupportedAudioFileException JavaDoc("could not get audio input stream from input stream");
1103    } else {
1104        return audioStream;
1105    }
1106    }
1107
1108    /**
1109     * Obtains an audio input stream from the URL provided. The URL must
1110     * point to valid audio file data.
1111     * @param url the URL for which the <code>AudioInputStream</code> should be
1112     * constructed
1113     * @return an <code>AudioInputStream</code> object based on the audio file data pointed
1114     * to by the URL
1115     * @throws UnsupportedAudioFileException if the URL does not point to valid audio
1116     * file data recognized by the system
1117     * @throws IOException if an I/O exception occurs
1118     */

1119    public static AudioInputStream JavaDoc getAudioInputStream(URL JavaDoc url)
1120    throws UnsupportedAudioFileException JavaDoc, IOException JavaDoc {
1121
1122    List JavaDoc providers = getAudioFileReaders();
1123    AudioInputStream JavaDoc audioStream = null;
1124
1125    for(int i = 0; i < providers.size(); i++ ) {
1126        AudioFileReader JavaDoc reader = (AudioFileReader JavaDoc) providers.get(i);
1127        try {
1128        audioStream = reader.getAudioInputStream( url ); // throws IOException
1129
break;
1130        } catch (UnsupportedAudioFileException JavaDoc e) {
1131        continue;
1132        }
1133    }
1134
1135    if( audioStream==null ) {
1136        throw new UnsupportedAudioFileException JavaDoc("could not get audio input stream from input URL");
1137    } else {
1138        return audioStream;
1139    }
1140    }
1141
1142    /**
1143     * Obtains an audio input stream from the provided <code>File</code>. The <code>File</code> must
1144     * point to valid audio file data.
1145     * @param file the <code>File</code> for which the <code>AudioInputStream</code> should be
1146     * constructed
1147     * @return an <code>AudioInputStream</code> object based on the audio file data pointed
1148     * to by the <code>File</code>
1149     * @throws UnsupportedAudioFileException if the <code>File</code> does not point to valid audio
1150     * file data recognized by the system
1151     * @throws IOException if an I/O exception occurs
1152     */

1153    public static AudioInputStream JavaDoc getAudioInputStream(File JavaDoc file)
1154    throws UnsupportedAudioFileException JavaDoc, IOException JavaDoc {
1155
1156    List JavaDoc providers = getAudioFileReaders();
1157    AudioInputStream JavaDoc audioStream = null;
1158
1159    for(int i = 0; i < providers.size(); i++ ) {
1160        AudioFileReader JavaDoc reader = (AudioFileReader JavaDoc) providers.get(i);
1161        try {
1162        audioStream = reader.getAudioInputStream( file ); // throws IOException
1163
break;
1164        } catch (UnsupportedAudioFileException JavaDoc e) {
1165        continue;
1166        }
1167    }
1168
1169    if( audioStream==null ) {
1170        throw new UnsupportedAudioFileException JavaDoc("could not get audio input stream from input file");
1171    } else {
1172        return audioStream;
1173    }
1174    }
1175
1176
1177    /**
1178     * Obtains the file types for which file writing support is provided by the system.
1179     * @return array of unique file types. If no file types are supported,
1180     * an array of length 0 is returned.
1181     */

1182    public static AudioFileFormat.Type JavaDoc[] getAudioFileTypes() {
1183    List JavaDoc providers = getAudioFileWriters();
1184    Set JavaDoc returnTypesSet = new HashSet JavaDoc();
1185
1186    for(int i=0; i < providers.size(); i++) {
1187        AudioFileWriter JavaDoc writer = (AudioFileWriter JavaDoc) providers.get(i);
1188        AudioFileFormat.Type JavaDoc[] fileTypes = writer.getAudioFileTypes();
1189        for(int j=0; j < fileTypes.length; j++) {
1190        returnTypesSet.add(fileTypes[j]);
1191        }
1192    }
1193    AudioFileFormat.Type JavaDoc returnTypes[] = (AudioFileFormat.Type JavaDoc[])
1194        returnTypesSet.toArray(new AudioFileFormat.Type JavaDoc[0]);
1195    return returnTypes;
1196    }
1197
1198
1199    /**
1200     * Indicates whether file writing support for the specified file type is provided
1201     * by the system.
1202     * @param fileType the file type for which write capabilities are queried
1203     * @return <code>true</code> if the file type is supported,
1204     * otherwise <code>false</code>
1205     */

1206    public static boolean isFileTypeSupported(AudioFileFormat.Type JavaDoc fileType) {
1207
1208    List JavaDoc providers = getAudioFileWriters();
1209
1210    for(int i=0; i < providers.size(); i++) {
1211        AudioFileWriter JavaDoc writer = (AudioFileWriter JavaDoc) providers.get(i);
1212        if (writer.isFileTypeSupported(fileType)) {
1213        return true;
1214        }
1215    }
1216    return false;
1217    }
1218
1219
1220    /**
1221     * Obtains the file types that the system can write from the
1222     * audio input stream specified.
1223     * @param stream the audio input stream for which audio file type support
1224     * is queried
1225     * @return array of file types. If no file types are supported,
1226     * an array of length 0 is returned.
1227     */

1228    public static AudioFileFormat.Type JavaDoc[] getAudioFileTypes(AudioInputStream JavaDoc stream) {
1229    List JavaDoc providers = getAudioFileWriters();
1230    Set JavaDoc returnTypesSet = new HashSet JavaDoc();
1231
1232    for(int i=0; i < providers.size(); i++) {
1233        AudioFileWriter JavaDoc writer = (AudioFileWriter JavaDoc) providers.get(i);
1234        AudioFileFormat.Type JavaDoc[] fileTypes = writer.getAudioFileTypes(stream);
1235        for(int j=0; j < fileTypes.length; j++) {
1236        returnTypesSet.add(fileTypes[j]);
1237        }
1238    }
1239    AudioFileFormat.Type JavaDoc returnTypes[] = (AudioFileFormat.Type JavaDoc[])
1240        returnTypesSet.toArray(new AudioFileFormat.Type JavaDoc[0]);
1241    return returnTypes;
1242    }
1243
1244
1245    /**
1246     * Indicates whether an audio file of the specified file type can be written
1247     * from the indicated audio input stream.
1248     * @param fileType the file type for which write capabilities are queried
1249     * @param stream the stream for which file-writing support is queried
1250     * @return <code>true</code> if the file type is supported for this audio input stream,
1251     * otherwise <code>false</code>
1252     */

1253    public static boolean isFileTypeSupported(AudioFileFormat.Type JavaDoc fileType,
1254                          AudioInputStream JavaDoc stream) {
1255
1256    List JavaDoc providers = getAudioFileWriters();
1257
1258    for(int i=0; i < providers.size(); i++) {
1259        AudioFileWriter JavaDoc writer = (AudioFileWriter JavaDoc) providers.get(i);
1260        if(writer.isFileTypeSupported(fileType, stream)) {
1261        return true;
1262        }
1263    }
1264    return false;
1265    }
1266
1267
1268    /**
1269     * Writes a stream of bytes representing an audio file of the specified file type
1270     * to the output stream provided. Some file types require that
1271     * the length be written into the file header; such files cannot be written from
1272     * start to finish unless the length is known in advance. An attempt
1273     * to write a file of such a type will fail with an IOException if the length in
1274     * the audio file type is <code>AudioSystem.NOT_SPECIFIED</code>.
1275     *
1276     * @param stream the audio input stream containing audio data to be
1277     * written to the file
1278     * @param fileType the kind of audio file to write
1279     * @param out the stream to which the file data should be written
1280     * @return the number of bytes written to the output stream
1281     * @throws IOException if an input/output exception occurs
1282     * @throws IllegalArgumentException if the file type is not supported by
1283     * the system
1284     * @see #isFileTypeSupported
1285     * @see #getAudioFileTypes
1286     */

1287    public static int write(AudioInputStream JavaDoc stream, AudioFileFormat.Type JavaDoc fileType,
1288                OutputStream JavaDoc out) throws IOException JavaDoc {
1289
1290    List JavaDoc providers = getAudioFileWriters();
1291    int bytesWritten = 0;
1292    boolean flag = false;
1293
1294    for(int i=0; i < providers.size(); i++) {
1295        AudioFileWriter JavaDoc writer = (AudioFileWriter JavaDoc) providers.get(i);
1296        try {
1297        bytesWritten = writer.write( stream, fileType, out ); // throws IOException
1298
flag = true;
1299        break;
1300        } catch (IllegalArgumentException JavaDoc e) {
1301        // thrown if this provider cannot write the sequence, try the next
1302
continue;
1303        }
1304    }
1305    if(!flag) {
1306        throw new IllegalArgumentException JavaDoc("could not write audio file: file type not supported: " + fileType);
1307    } else {
1308        return bytesWritten;
1309    }
1310    }
1311
1312
1313    /**
1314     * Writes a stream of bytes representing an audio file of the specified file type
1315     * to the external file provided.
1316     * @param stream the audio input stream containing audio data to be
1317     * written to the file
1318     * @param fileType the kind of audio file to write
1319     * @param out the external file to which the file data should be written
1320     * @return the number of bytes written to the file
1321     * @throws IOException if an I/O exception occurs
1322     * @throws IllegalArgumentException if the file type is not supported by
1323     * the system
1324     * @see #isFileTypeSupported
1325     * @see #getAudioFileTypes
1326     */

1327    public static int write(AudioInputStream JavaDoc stream, AudioFileFormat.Type JavaDoc fileType,
1328                File JavaDoc out) throws IOException JavaDoc {
1329
1330    List JavaDoc providers = getAudioFileWriters();
1331    int bytesWritten = 0;
1332    boolean flag = false;
1333
1334    for(int i=0; i < providers.size(); i++) {
1335        AudioFileWriter JavaDoc writer = (AudioFileWriter JavaDoc) providers.get(i);
1336        try {
1337        bytesWritten = writer.write( stream, fileType, out ); // throws IOException
1338
flag = true;
1339        break;
1340        } catch (IllegalArgumentException JavaDoc e) {
1341        // thrown if this provider cannot write the sequence, try the next
1342
continue;
1343        }
1344    }
1345    if (!flag) {
1346        throw new IllegalArgumentException JavaDoc("could not write audio file: file type not supported: " + fileType);
1347    } else {
1348        return bytesWritten;
1349    }
1350    }
1351
1352
1353    // METHODS FOR INTERNAL IMPLEMENTATION USE
1354

1355    /**
1356     * Obtains the set of MixerProviders on the system.
1357     */

1358    private static List JavaDoc getMixerProviders() {
1359    return getProviders(MixerProvider JavaDoc.class);
1360    }
1361
1362
1363    /**
1364     * Obtains the set of format converters (codecs, transcoders, etc.)
1365     * that are currently installed on the system.
1366     * @return an array of
1367     * {@link javax.sound.sampled.spi.FormatConversionProvider
1368     * FormatConversionProvider}
1369     * objects representing the available format converters. If no format
1370     * converters readers are available on the system, an array of length 0 is
1371     * returned.
1372     */

1373    private static List JavaDoc getFormatConversionProviders() {
1374    return getProviders(FormatConversionProvider JavaDoc.class);
1375    }
1376
1377
1378    /**
1379     * Obtains the set of audio file readers that are currently installed on the system.
1380     * @return a List of
1381     * {@link javax.sound.sampled.spi.AudioFileReader
1382     * AudioFileReader}
1383     * objects representing the installed audio file readers. If no audio file
1384     * readers are available on the system, an empty List is returned.
1385     */

1386    private static List JavaDoc getAudioFileReaders() {
1387    return getProviders(AudioFileReader JavaDoc.class);
1388    }
1389
1390
1391    /**
1392     * Obtains the set of audio file writers that are currently installed on the system.
1393     * @return a List of
1394     * {@link javax.sound.samples.spi.AudioFileWriter AudioFileWriter}
1395     * objects representing the available audio file writers. If no audio file
1396     * writers are available on the system, an empty List is returned.
1397     */

1398    private static List JavaDoc getAudioFileWriters() {
1399    return getProviders(AudioFileWriter JavaDoc.class);
1400    }
1401
1402
1403
1404    /** Attempts to locate and return a default Mixer that provides lines
1405     * of the specified type.
1406     *
1407     * @param providers the installed mixer providers
1408     * @param info The requested line type
1409     * TargetDataLine.class, Clip.class or Port.class.
1410     * @return a Mixer that matches the requirements, or null if no default mixer found
1411     */

1412    private static Mixer JavaDoc getDefaultMixer(List JavaDoc providers, Line.Info JavaDoc info) {
1413    Class JavaDoc lineClass = info.getLineClass();
1414    String JavaDoc providerClassName = JDK13Services.getDefaultProviderClassName(lineClass);
1415    String JavaDoc instanceName = JDK13Services.getDefaultInstanceName(lineClass);
1416    Mixer JavaDoc mixer;
1417
1418    if (providerClassName != null) {
1419        MixerProvider JavaDoc defaultProvider = getNamedProvider(providerClassName, providers);
1420        if (defaultProvider != null) {
1421        if (instanceName != null) {
1422            mixer = getNamedMixer(instanceName, defaultProvider, info);
1423            if (mixer != null) {
1424            return mixer;
1425            }
1426        } else {
1427            mixer = getFirstMixer(defaultProvider, info,
1428                      false /* mixing not required*/);
1429            if (mixer != null) {
1430            return mixer;
1431            }
1432        }
1433
1434        }
1435    }
1436
1437    /* Provider class not specified or
1438       provider class cannot be found, or
1439       provider class and instance specified and instance cannot be found or is not appropriate */

1440    if (instanceName != null) {
1441        mixer = getNamedMixer(instanceName, providers, info);
1442        if (mixer != null) {
1443        return mixer;
1444        }
1445    }
1446
1447
1448    /* No default are specified, or if something is specified, everything
1449       failed. */

1450    return null;
1451    }
1452
1453
1454
1455    /** Return a MixerProvider of a given class from the list of
1456    MixerProviders.
1457
1458    This method never requires the returned Mixer to do mixing.
1459    @param providerClassName The class name of the provider to be returned.
1460    @param providers The list of MixerProviders that is searched.
1461    @return A MixerProvider of the requested class, or null if none is
1462    found.
1463     */

1464    private static MixerProvider JavaDoc getNamedProvider(String JavaDoc providerClassName,
1465                          List JavaDoc providers) {
1466    for(int i = 0; i < providers.size(); i++) {
1467        MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
1468        if (provider.getClass().getName().equals(providerClassName)) {
1469        return provider;
1470        }
1471    }
1472    return null;
1473    }
1474
1475
1476    /** Return a Mixer with a given name from a given MixerProvider.
1477      This method never requires the returned Mixer to do mixing.
1478      @param mixerName The name of the Mixer to be returned.
1479      @param provider The MixerProvider to check for Mixers.
1480      @param info The type of line the returned Mixer is required to
1481      support.
1482
1483      @return A Mixer matching the requirements, or null if none is found.
1484     */

1485    private static Mixer JavaDoc getNamedMixer(String JavaDoc mixerName,
1486                       MixerProvider JavaDoc provider,
1487                       Line.Info JavaDoc info) {
1488    Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
1489    for (int i = 0; i < infos.length; i++) {
1490        if (infos[i].getName().equals(mixerName)) {
1491        Mixer JavaDoc mixer = provider.getMixer(infos[i]);
1492        if (isAppropriateMixer(mixer, info, false)) {
1493            return mixer;
1494        }
1495        }
1496    }
1497    return null;
1498    }
1499
1500
1501    /** From a List of MixerProviders, return a Mixer with a given name.
1502    This method never requires the returned Mixer to do mixing.
1503    @param mixerName The name of the Mixer to be returned.
1504    @param providers The List of MixerProviders to check for Mixers.
1505    @param info The type of line the returned Mixer is required to
1506    support.
1507    @return A Mixer matching the requirements, or null if none is found.
1508     */

1509    private static Mixer JavaDoc getNamedMixer(String JavaDoc mixerName,
1510                       List JavaDoc providers,
1511                       Line.Info JavaDoc info) {
1512    for(int i = 0; i < providers.size(); i++) {
1513        MixerProvider JavaDoc provider = (MixerProvider JavaDoc) providers.get(i);
1514        Mixer JavaDoc mixer = getNamedMixer(mixerName, provider, info);
1515        if (mixer != null) {
1516        return mixer;
1517        }
1518    }
1519    return null;
1520    }
1521
1522
1523    /** From a given MixerProvider, return the first appropriate Mixer.
1524    @param provider The MixerProvider to check for Mixers.
1525    @param info The type of line the returned Mixer is required to
1526    support.
1527    @param isMixingRequired If true, only Mixers that support mixing are
1528    returned for line types of SourceDataLine and Clip.
1529
1530    @return A Mixer that is considered appropriate, or null
1531    if none is found.
1532     */

1533    private static Mixer JavaDoc getFirstMixer(MixerProvider JavaDoc provider,
1534                       Line.Info JavaDoc info,
1535                       boolean isMixingRequired) {
1536    Mixer.Info JavaDoc[] infos = provider.getMixerInfo();
1537    for (int j = 0; j < infos.length; j++) {
1538        Mixer JavaDoc mixer = provider.getMixer(infos[j]);
1539        if (isAppropriateMixer(mixer, info, isMixingRequired)) {
1540        return mixer;
1541        }
1542    }
1543    return null;
1544    }
1545
1546
1547    /** Checks if a Mixer is appropriate.
1548    A Mixer is considered appropriate if it support the given line type.
1549    If isMixingRequired is true and the line type is an output one
1550    (SourceDataLine, Clip), the mixer is appropriate if it supports
1551    at least 2 (concurrent) lines of the given type.
1552
1553    @return true if the mixer is considered appropriate according to the
1554    rules given above, false otherwise.
1555     */

1556    private static boolean isAppropriateMixer(Mixer JavaDoc mixer,
1557                          Line.Info JavaDoc lineInfo,
1558                          boolean isMixingRequired) {
1559    if (! mixer.isLineSupported(lineInfo)) {
1560        return false;
1561    }
1562    Class JavaDoc lineClass = lineInfo.getLineClass();
1563    if (isMixingRequired
1564        && (SourceDataLine JavaDoc.class.isAssignableFrom(lineClass) ||
1565        Clip JavaDoc.class.isAssignableFrom(lineClass))) {
1566        int maxLines = mixer.getMaxLines(lineInfo);
1567        return ((maxLines == NOT_SPECIFIED) || (maxLines > 1));
1568    }
1569    return true;
1570    }
1571
1572
1573
1574    /**
1575     * Like getMixerInfo, but return List
1576     */

1577    private static List JavaDoc getMixerInfoList() {
1578    List JavaDoc providers = getMixerProviders();
1579    return getMixerInfoList(providers);
1580    }
1581
1582
1583    /**
1584     * Like getMixerInfo, but return List
1585     */

1586    private static List JavaDoc getMixerInfoList(List JavaDoc providers) {
1587    List JavaDoc infos = new ArrayList JavaDoc();
1588
1589    Mixer.Info JavaDoc[] someInfos; // per-mixer
1590
Mixer.Info JavaDoc[] allInfos; // for all mixers
1591

1592    for(int i = 0; i < providers.size(); i++ ) {
1593        someInfos = (Mixer.Info JavaDoc[])
1594        ((MixerProvider JavaDoc)providers.get(i)).getMixerInfo();
1595
1596        for (int j = 0; j < someInfos.length; j++) {
1597        infos.add(someInfos[j]);
1598        }
1599    }
1600
1601    return infos;
1602    }
1603
1604
1605    /**
1606     * Obtains the set of services currently installed on the system
1607     * using sun.misc.Service, the SPI mechanism in 1.3.
1608     * @return a List of instances of providers for the requested service.
1609     * If no providers are available, a vector of length 0 will be returned.
1610     */

1611    private static List JavaDoc getProviders(Class JavaDoc providerClass) {
1612    return JDK13Services.getProviders(providerClass);
1613    }
1614}
1615
Popular Tags