001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.sound.sampled;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.net.URL;
025: import java.util.ArrayList;
026: import java.util.List;
027: import java.util.Iterator;
028: import java.util.Properties;
029:
030: import javax.sound.sampled.spi.AudioFileReader;
031: import javax.sound.sampled.spi.AudioFileWriter;
032: import javax.sound.sampled.spi.FormatConversionProvider;
033: import javax.sound.sampled.spi.MixerProvider;
034:
035: import org.apache.harmony.sound.utils.ProviderService;
036:
037: import org.apache.harmony.sound.internal.nls.Messages;
038:
039: public class AudioSystem {
040:
041: public static final int NOT_SPECIFIED = -1;
042:
043: private final static String audioFileReaderPath = "META-INF/services/javax.sound.sampled.spi.AudioFileReader"; //$NON-NLS-1$
044:
045: private final static String audioFileWriterPath = "META-INF/services/javax.sound.sampled.spi.AudioFileWriter"; //$NON-NLS-1$
046:
047: private final static String formatConversionProviderPath = "META-INF/services/javax.sound.sampled.spi.FormatConversionProvider"; //$NON-NLS-1$
048:
049: private final static String mixerProviderPath = "META-INF/services/javax.sound.sampled.spi.MixerProvider"; //$NON-NLS-1$
050:
051: private final static String CLIP = "javax.sound.sampled.Clip"; //$NON-NLS-1$
052:
053: private final static String PORT = "javax.sound.sampled.Port"; //$NON-NLS-1$
054:
055: private final static String SOURCEDATALINE = "javax.sound.sampled.SourceDataLine"; //$NON-NLS-1$
056:
057: private final static String TARGETDATALINE = "javax.sound.sampled.TargetDataLine"; //$NON-NLS-1$
058:
059: // This class does not have public constructor
060: private AudioSystem() {
061: }
062:
063: public static Mixer.Info[] getMixerInfo() {
064: List<Mixer.Info> result = new ArrayList<Mixer.Info>();
065: for (Iterator providers = ProviderService.getProviders(
066: mixerProviderPath).iterator(); providers.hasNext();) {
067: try {
068: Mixer.Info[] infos = ((MixerProvider) (providers.next()))
069: .getMixerInfo();
070: for (Mixer.Info info : infos) {
071: result.add(info);
072: }
073: } catch (ClassCastException e) {
074: }
075: }
076: Mixer.Info[] temp = new Mixer.Info[result.size()];
077: return result.toArray(temp);
078: }
079:
080: public static Mixer getMixer(Mixer.Info info) {
081: Mixer.Info[] infos;
082: Mixer.Info inf;
083: if (info == null) {
084: infos = getMixerInfo();
085: if (infos == null) {
086: throw new IllegalArgumentException(
087: "No system default mixer installed"); //$NON-NLS-1$
088: }
089: inf = infos[0];
090: } else {
091: inf = info;
092: }
093:
094: for (Iterator providers = ProviderService.getProviders(
095: mixerProviderPath).iterator(); providers.hasNext();) {
096: try {
097: return ((MixerProvider) (providers.next()))
098: .getMixer(inf);
099: } catch (ClassCastException e) {
100: } catch (IllegalArgumentException e) {
101: }
102: }
103: throw new IllegalArgumentException(
104: "Mixer not supported: " + inf); //$NON-NLS-1$
105: }
106:
107: public static Line.Info[] getSourceLineInfo(Line.Info info) {
108: List<Line.Info> result = new ArrayList<Line.Info>();
109: for (Iterator providers = ProviderService.getProviders(
110: mixerProviderPath).iterator(); providers.hasNext();) {
111: try {
112: MixerProvider pr = (MixerProvider) providers.next();
113: Mixer.Info[] mixinfos = pr.getMixerInfo();
114: for (Mixer.Info mixinfo : mixinfos) {
115: Mixer mix = pr.getMixer(mixinfo);
116: Line.Info[] linfos = mix.getSourceLineInfo(info);
117: for (Line.Info linfo : linfos) {
118: result.add(linfo);
119: }
120: }
121: } catch (ClassCastException e) {
122: }
123: }
124: Line.Info[] temp = new Line.Info[result.size()];
125: return result.toArray(temp);
126: }
127:
128: public static Line.Info[] getTargetLineInfo(Line.Info info) {
129: List<Line.Info> result = new ArrayList<Line.Info>();
130: for (Iterator providers = ProviderService.getProviders(
131: mixerProviderPath).iterator(); providers.hasNext();) {
132: try {
133: MixerProvider pr = (MixerProvider) providers.next();
134: Mixer.Info[] mixinfos = pr.getMixerInfo();
135: for (Mixer.Info mixinfo : mixinfos) {
136: Mixer mix = pr.getMixer(mixinfo);
137: Line.Info[] linfos = mix.getTargetLineInfo(info);
138: for (Line.Info linfo : linfos) {
139: result.add(linfo);
140: }
141: }
142: } catch (ClassCastException e) {
143: }
144: }
145: Line.Info[] temp = new Line.Info[result.size()];
146: return result.toArray(temp);
147: }
148:
149: public static boolean isLineSupported(Line.Info info) {
150:
151: for (Iterator providers = ProviderService.getProviders(
152: mixerProviderPath).iterator(); providers.hasNext();) {
153: try {
154: MixerProvider pr = (MixerProvider) providers.next();
155: Mixer.Info[] mixinfos = pr.getMixerInfo();
156: for (Mixer.Info mixinfo : mixinfos) {
157: Mixer mix = pr.getMixer(mixinfo);
158: if (mix.isLineSupported(info)) {
159: return true;
160: }
161: }
162: } catch (ClassCastException e) {
163: }
164: }
165: return false;
166: }
167:
168: private static Mixer getMixer(String propVal, Line.Info info,
169: List<?> mixerProviders) {
170:
171: int index = propVal.indexOf("#"); //$NON-NLS-1$
172: String className;
173: String mixName;
174: if (index == -1) {
175: className = propVal.trim();
176: mixName = ""; //$NON-NLS-1$
177: } else {
178: className = propVal.substring(0, index).trim();
179: if (index == propVal.length()) {
180: mixName = ""; //$NON-NLS-1$
181: } else {
182: mixName = propVal.substring(index + 1).trim();
183: }
184: }
185: Mixer.Info[] minfos = null;
186: if (!className.equals("")) { //$NON-NLS-1$
187: for (Iterator providers = mixerProviders.iterator(); providers
188: .hasNext();) {
189: try {
190: MixerProvider pr = (MixerProvider) (providers
191: .next());
192: if (className.equals(pr.getClass().getName())) {
193: minfos = pr.getMixerInfo();
194: break;
195: }
196: } catch (ClassCastException e) {
197: }
198: }
199: }
200: if (minfos == null) {
201: minfos = getMixerInfo();
202: }
203:
204: if (!mixName.equals("")) { //$NON-NLS-1$
205: for (Mixer.Info minfo : minfos) {
206: if (mixName.equals(minfo.getName())) {
207: return getMixer(minfo);
208: }
209: }
210: }
211: if (minfos.length > 0) {
212: return getMixer(minfos[0]);
213: }
214: return null;
215: }
216:
217: public static Line getLine(Line.Info info)
218: throws LineUnavailableException {
219: String propName = null;
220: Class lineClass = info.getLineClass();
221:
222: if (Clip.class.isAssignableFrom(lineClass)) {
223: propName = CLIP;
224: } else if (Port.class.isAssignableFrom(lineClass)) {
225: propName = PORT;
226: } else if (SourceDataLine.class.isAssignableFrom(lineClass)) {
227: propName = SOURCEDATALINE;
228: } else if (TargetDataLine.class.isAssignableFrom(lineClass)) {
229: propName = TARGETDATALINE;
230: }
231: return getLine(propName, info);
232: }
233:
234: private static Line getLine(String propName, Line.Info info)
235: throws LineUnavailableException {
236:
237: List<?> mixerProviders = ProviderService
238: .getProviders(mixerProviderPath);
239:
240: if (propName != null) {
241: String propVal = System.getProperty(propName);
242: if (propVal != null) {
243: Mixer m = getMixer(propVal, info, mixerProviders);
244: if (m != null) {
245: Line l = m.getLine(info);
246: if (l != null) {
247: return l;
248: }
249: }
250: }
251:
252: Properties soundProperties = ProviderService
253: .getSoundProperties();
254: propVal = soundProperties.getProperty(propName);
255: if (propVal != null) {
256: Mixer m = getMixer(propVal, info, mixerProviders);
257: if (m != null) {
258: Line l = m.getLine(info);
259: if (l != null) {
260: return l;
261: }
262: }
263: }
264: }
265:
266: for (Iterator providers = ProviderService.getProviders(
267: mixerProviderPath).iterator(); providers.hasNext();) {
268: try {
269: MixerProvider pr = (MixerProvider) (providers.next());
270: Mixer.Info[] mixinfos = pr.getMixerInfo();
271: for (Mixer.Info mixinfo : mixinfos) {
272: try {
273: Mixer mix = pr.getMixer(mixinfo);
274: return mix.getLine(info);
275: } catch (IllegalArgumentException e) {
276: // continue
277: }
278: }
279: } catch (ClassCastException e) {
280: }
281: }
282: // sound.11=Could not get line
283: throw new IllegalArgumentException(Messages
284: .getString("sound.11")); //$NON-NLS-1$
285: }
286:
287: public static Clip getClip() throws LineUnavailableException {
288: return (Clip) getLine(new Line.Info(Clip.class));
289: }
290:
291: public static Clip getClip(Mixer.Info mixerInfo)
292: throws LineUnavailableException {
293: return (Clip) (getMixer(mixerInfo).getLine(new Line.Info(
294: Clip.class)));
295: }
296:
297: public static SourceDataLine getSourceDataLine(AudioFormat format)
298: throws LineUnavailableException {
299: SourceDataLine line = (SourceDataLine) getLine(new Line.Info(
300: SourceDataLine.class));
301: line.open(format);
302: return line;
303: }
304:
305: public static SourceDataLine getSourceDataLine(AudioFormat format,
306: Mixer.Info mixerinfo) throws LineUnavailableException {
307:
308: SourceDataLine line = (SourceDataLine) getMixer(mixerinfo)
309: .getLine(new Line.Info(SourceDataLine.class));
310: line.open(format);
311: return line;
312: }
313:
314: public static TargetDataLine getTargetDataLine(AudioFormat format)
315: throws LineUnavailableException {
316: TargetDataLine line = (TargetDataLine) getLine(new Line.Info(
317: TargetDataLine.class));
318: line.open(format);
319: return line;
320: }
321:
322: public static TargetDataLine getTargetDataLine(AudioFormat format,
323: Mixer.Info mixerinfo) throws LineUnavailableException {
324:
325: TargetDataLine line = (TargetDataLine) getMixer(mixerinfo)
326: .getLine(new Line.Info(TargetDataLine.class));
327: line.open(format);
328: return line;
329: }
330:
331: public static AudioFormat.Encoding[] getTargetEncodings(
332: AudioFormat.Encoding sourceEncoding) {
333:
334: List<AudioFormat.Encoding> result = new ArrayList<AudioFormat.Encoding>();
335: for (Iterator providers = ProviderService.getProviders(
336: formatConversionProviderPath).iterator(); providers
337: .hasNext();) {
338: try {
339: FormatConversionProvider pr = (FormatConversionProvider) providers
340: .next();
341: if (!pr.isSourceEncodingSupported(sourceEncoding)) {
342: continue;
343: }
344: AudioFormat.Encoding[] encodings = pr
345: .getTargetEncodings();
346: for (AudioFormat.Encoding encoding : encodings) {
347: result.add(encoding);
348: }
349: } catch (ClassCastException e) {
350: }
351: }
352: AudioFormat.Encoding[] temp = new AudioFormat.Encoding[result
353: .size()];
354: return result.toArray(temp);
355: }
356:
357: public static AudioFormat.Encoding[] getTargetEncodings(
358: AudioFormat sourceFormat) {
359:
360: List<AudioFormat.Encoding> result = new ArrayList<AudioFormat.Encoding>();
361: for (Iterator providers = ProviderService.getProviders(
362: formatConversionProviderPath).iterator(); providers
363: .hasNext();) {
364: try {
365: AudioFormat.Encoding[] encodings = ((FormatConversionProvider) (providers
366: .next())).getTargetEncodings(sourceFormat);
367: for (AudioFormat.Encoding encoding : encodings) {
368: result.add(encoding);
369: }
370: } catch (ClassCastException e) {
371: }
372: }
373: AudioFormat.Encoding[] temp = new AudioFormat.Encoding[result
374: .size()];
375: return result.toArray(temp);
376: }
377:
378: public static boolean isConversionSupported(
379: AudioFormat.Encoding targetEncoding,
380: AudioFormat sourceFormat) {
381:
382: for (Iterator providers = ProviderService.getProviders(
383: formatConversionProviderPath).iterator(); providers
384: .hasNext();) {
385: if (((FormatConversionProvider) (providers.next()))
386: .isConversionSupported(targetEncoding, sourceFormat)) {
387: return true;
388: }
389: }
390: return false;
391: }
392:
393: public static AudioInputStream getAudioInputStream(
394: AudioFormat.Encoding targetEncoding,
395: AudioInputStream sourceStream) {
396:
397: if (sourceStream.getFormat().getEncoding().equals(
398: targetEncoding)) {
399: return sourceStream;
400: }
401: for (Iterator providers = ProviderService.getProviders(
402: formatConversionProviderPath).iterator(); providers
403: .hasNext();) {
404: try {
405: return ((FormatConversionProvider) (providers.next()))
406: .getAudioInputStream(targetEncoding,
407: sourceStream);
408: } catch (ClassCastException e) {
409: } catch (IllegalArgumentException e) {
410: }
411: }
412: // sound.12=Could not get audio input stream from source stream
413: throw new IllegalArgumentException(Messages
414: .getString("sound.12")); //$NON-NLS-1$
415: }
416:
417: public static AudioFormat[] getTargetFormats(
418: AudioFormat.Encoding targetEncoding,
419: AudioFormat sourceFormat) {
420:
421: List<AudioFormat> result = new ArrayList<AudioFormat>();
422: for (Iterator providers = ProviderService.getProviders(
423: formatConversionProviderPath).iterator(); providers
424: .hasNext();) {
425: try {
426: AudioFormat[] formats = ((FormatConversionProvider) (providers
427: .next())).getTargetFormats(targetEncoding,
428: sourceFormat);
429: for (AudioFormat format : formats) {
430: result.add(format);
431: }
432: } catch (ClassCastException e) {
433: }
434: }
435: AudioFormat[] temp = new AudioFormat[result.size()];
436: return result.toArray(temp);
437: }
438:
439: public static boolean isConversionSupported(
440: AudioFormat targetFormat, AudioFormat sourceFormat) {
441:
442: for (Iterator providers = ProviderService.getProviders(
443: formatConversionProviderPath).iterator(); providers
444: .hasNext();) {
445: if (((FormatConversionProvider) (providers.next()))
446: .isConversionSupported(targetFormat, sourceFormat)) {
447: return true;
448: }
449: }
450: return false;
451: }
452:
453: public static AudioInputStream getAudioInputStream(
454: AudioFormat targetFormat, AudioInputStream sourceStream) {
455:
456: if (sourceStream.getFormat().matches(targetFormat)) {
457: return sourceStream;
458: }
459: for (Iterator providers = ProviderService.getProviders(
460: formatConversionProviderPath).iterator(); providers
461: .hasNext();) {
462: try {
463: return ((FormatConversionProvider) (providers.next()))
464: .getAudioInputStream(targetFormat, sourceStream);
465: } catch (ClassCastException e) {
466: } catch (IllegalArgumentException e) {
467: }
468: }
469: // sound.13=Could not get audio input stream from source stream
470: throw new IllegalArgumentException(Messages
471: .getString("sound.13")); //$NON-NLS-1$
472: }
473:
474: public static AudioFileFormat getAudioFileFormat(InputStream stream)
475: throws UnsupportedAudioFileException, IOException {
476:
477: for (Iterator providers = ProviderService.getProviders(
478: audioFileReaderPath).iterator(); providers.hasNext();) {
479: try {
480: return ((AudioFileReader) (providers.next()))
481: .getAudioFileFormat(stream);
482: } catch (ClassCastException e) {
483: } catch (UnsupportedAudioFileException e) {
484: }
485: }
486: // sound.14=File is not a supported file type
487: throw new UnsupportedAudioFileException(Messages
488: .getString("sound.14")); //$NON-NLS-1$
489: }
490:
491: public static AudioFileFormat getAudioFileFormat(URL url)
492: throws UnsupportedAudioFileException, IOException {
493:
494: for (Iterator providers = ProviderService.getProviders(
495: audioFileReaderPath).iterator(); providers.hasNext();) {
496: try {
497: return ((AudioFileReader) (providers.next()))
498: .getAudioFileFormat(url);
499: } catch (ClassCastException e) {
500: } catch (UnsupportedAudioFileException e) {
501: }
502: }
503: // sound.14=File is not a supported file type
504: throw new UnsupportedAudioFileException(Messages
505: .getString("sound.14")); //$NON-NLS-1$
506: }
507:
508: public static AudioFileFormat getAudioFileFormat(File file)
509: throws UnsupportedAudioFileException, IOException {
510:
511: for (Iterator providers = ProviderService.getProviders(
512: audioFileReaderPath).iterator(); providers.hasNext();) {
513: try {
514: return ((AudioFileReader) (providers.next()))
515: .getAudioFileFormat(file);
516: } catch (ClassCastException e) {
517: } catch (UnsupportedAudioFileException e) {
518: }
519: }
520: // sound.14=File is not a supported file type
521: throw new UnsupportedAudioFileException(Messages
522: .getString("sound.14")); //$NON-NLS-1$
523: }
524:
525: public static AudioInputStream getAudioInputStream(
526: InputStream stream) throws UnsupportedAudioFileException,
527: IOException {
528:
529: if (stream instanceof AudioInputStream) {
530: return (AudioInputStream) stream;
531: }
532: for (Iterator providers = ProviderService.getProviders(
533: audioFileReaderPath).iterator(); providers.hasNext();) {
534: try {
535: return ((AudioFileReader) (providers.next()))
536: .getAudioInputStream(stream);
537: } catch (ClassCastException e) {
538: } catch (UnsupportedAudioFileException e) {
539: }
540: }
541: // sound.15=Could not get audio input stream from input stream
542: throw new UnsupportedAudioFileException(Messages
543: .getString("sound.15")); //$NON-NLS-1$
544: }
545:
546: public static AudioInputStream getAudioInputStream(URL url)
547: throws UnsupportedAudioFileException, IOException {
548:
549: for (Iterator providers = ProviderService.getProviders(
550: audioFileReaderPath).iterator(); providers.hasNext();) {
551: try {
552: return ((AudioFileReader) (providers.next()))
553: .getAudioInputStream(url);
554: } catch (ClassCastException e) {
555: } catch (UnsupportedAudioFileException e) {
556: }
557: }
558: // sound.16=Could not get audio input stream from input URL
559: throw new UnsupportedAudioFileException(Messages
560: .getString("sound.16")); //$NON-NLS-1$
561: }
562:
563: public static AudioInputStream getAudioInputStream(File file)
564: throws UnsupportedAudioFileException, IOException {
565:
566: for (Iterator providers = ProviderService.getProviders(
567: audioFileReaderPath).iterator(); providers.hasNext();) {
568: try {
569: return ((AudioFileReader) (providers.next()))
570: .getAudioInputStream(file);
571: } catch (ClassCastException e) {
572: } catch (UnsupportedAudioFileException e) {
573: }
574: }
575: // sound.17=Could not get audio input stream from input file
576: throw new UnsupportedAudioFileException(Messages
577: .getString("sound.17")); //$NON-NLS-1$
578: }
579:
580: public static AudioFileFormat.Type[] getAudioFileTypes() {
581: List<AudioFileFormat.Type> result = new ArrayList<AudioFileFormat.Type>();
582: for (Iterator providers = ProviderService.getProviders(
583: audioFileWriterPath).iterator(); providers.hasNext();) {
584: try {
585: AudioFileFormat.Type[] types = ((AudioFileWriter) (providers
586: .next())).getAudioFileTypes();
587: for (AudioFileFormat.Type type : types) {
588: result.add(type);
589: }
590: } catch (ClassCastException e) {
591: }
592: }
593: AudioFileFormat.Type[] temp = new AudioFileFormat.Type[result
594: .size()];
595: return result.toArray(temp);
596: }
597:
598: public static boolean isFileTypeSupported(
599: AudioFileFormat.Type fileType) {
600:
601: for (Iterator providers = ProviderService.getProviders(
602: audioFileWriterPath).iterator(); providers.hasNext();) {
603: if (((AudioFileWriter) (providers.next()))
604: .isFileTypeSupported(fileType)) {
605: return true;
606: }
607: }
608: return false;
609: }
610:
611: public static AudioFileFormat.Type[] getAudioFileTypes(
612: AudioInputStream stream) {
613: List<AudioFileFormat.Type> result = new ArrayList<AudioFileFormat.Type>();
614: for (Iterator providers = ProviderService.getProviders(
615: audioFileWriterPath).iterator(); providers.hasNext();) {
616: try {
617: AudioFileFormat.Type[] types = ((AudioFileWriter) (providers
618: .next())).getAudioFileTypes(stream);
619: for (AudioFileFormat.Type type : types) {
620: result.add(type);
621: }
622: } catch (ClassCastException e) {
623: }
624: }
625: AudioFileFormat.Type[] temp = new AudioFileFormat.Type[result
626: .size()];
627: return result.toArray(temp);
628: }
629:
630: public static boolean isFileTypeSupported(
631: AudioFileFormat.Type fileType, AudioInputStream stream) {
632:
633: for (Iterator providers = ProviderService.getProviders(
634: audioFileWriterPath).iterator(); providers.hasNext();) {
635: if (((AudioFileWriter) (providers.next()))
636: .isFileTypeSupported(fileType, stream)) {
637: return true;
638: }
639: }
640: return false;
641: }
642:
643: public static int write(AudioInputStream stream,
644: AudioFileFormat.Type fileType, OutputStream out)
645: throws IOException {
646: AudioFileWriter writer;
647: for (Iterator providers = ProviderService.getProviders(
648: audioFileWriterPath).iterator(); providers.hasNext();) {
649: writer = (AudioFileWriter) (providers.next());
650: if (writer.isFileTypeSupported(fileType, stream)) {
651: return writer.write(stream, fileType, out);
652: }
653: }
654: // sound.18=Type is not supported
655: throw new IllegalArgumentException(Messages
656: .getString("sound.18")); //$NON-NLS-1$
657: }
658:
659: public static int write(AudioInputStream stream,
660: AudioFileFormat.Type fileType, File out) throws IOException {
661: AudioFileWriter writer;
662: for (Iterator providers = ProviderService.getProviders(
663: audioFileWriterPath).iterator(); providers.hasNext();) {
664: writer = (AudioFileWriter) (providers.next());
665: if (writer.isFileTypeSupported(fileType, stream)) {
666: return writer.write(stream, fileType, out);
667: }
668: }
669: // sound.18=Type is not supported
670: throw new IllegalArgumentException(Messages
671: .getString("sound.18")); //$NON-NLS-1$
672: }
673: }
|