Source for javax.sound.sampled.AudioSystem

   1: /* Main interface to audio system
   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.sampled;
  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.HashSet;
  49: import java.util.Iterator;
  50: 
  51: import javax.sound.sampled.spi.AudioFileReader;
  52: import javax.sound.sampled.spi.AudioFileWriter;
  53: import javax.sound.sampled.spi.FormatConversionProvider;
  54: import javax.sound.sampled.spi.MixerProvider;
  55: 
  56: /**
  57:  * This clas is the primary interface to the audio system.  It contains
  58:  * a number of static methods which can be used to access this package's
  59:  * functionality.
  60:  *
  61:  * @since 1.3
  62:  */
  63: public class AudioSystem
  64: {
  65:   /**
  66:    * A constant which can be passed to a number of methods in this package,
  67:    * to indicate an unspecified value.
  68:    */
  69:   public static final int NOT_SPECIFIED = -1;
  70: 
  71:   // This class is not instantiable.
  72:   private AudioSystem()
  73:   {
  74:   }
  75: 
  76:   /**
  77:    * Return the file format of a given File.
  78:    * @param f the file to check
  79:    * @return the format of the file
  80:    * @throws UnsupportedAudioFileException if the file's format is not
  81:    * recognized
  82:    * @throws IOException if there is an I/O error reading the file
  83:    */
  84:   public static AudioFileFormat getAudioFileFormat(File f)
  85:     throws UnsupportedAudioFileException, IOException
  86:   {
  87:     Iterator<AudioFileReader> i = ServiceFactory.lookupProviders(AudioFileReader.class);
  88:     while (i.hasNext())
  89:       {
  90:         AudioFileReader reader = i.next();
  91:         try
  92:           {
  93:             return reader.getAudioFileFormat(f);
  94:           }
  95:         catch (UnsupportedAudioFileException _)
  96:           {
  97:             // Try the next provider.
  98:           }
  99:       }
 100:     throw new UnsupportedAudioFileException("file type not recognized");
 101:   }
 102: 
 103:   /**
 104:    * Return the file format of a given input stream.
 105:    * @param is the input stream to check
 106:    * @return the format of the stream
 107:    * @throws UnsupportedAudioFileException if the stream's format is not
 108:    * recognized
 109:    * @throws IOException if there is an I/O error reading the stream
 110:    */
 111:   public static AudioFileFormat getAudioFileFormat(InputStream is)
 112:     throws UnsupportedAudioFileException, IOException
 113:   {
 114:     Iterator<AudioFileReader> i = ServiceFactory.lookupProviders(AudioFileReader.class);
 115:     while (i.hasNext())
 116:       {
 117:         AudioFileReader reader = i.next();
 118:         try
 119:           {
 120:             return reader.getAudioFileFormat(is);
 121:           }
 122:         catch (UnsupportedAudioFileException _)
 123:           {
 124:             // Try the next provider.
 125:           }
 126:       }
 127:     throw new UnsupportedAudioFileException("input stream type not recognized");
 128:   }
 129: 
 130:   /**
 131:    * Return the file format of a given URL.
 132:    * @param url the URL to check
 133:    * @return the format of the URL
 134:    * @throws UnsupportedAudioFileException if the URL's format is not
 135:    * recognized
 136:    * @throws IOException if there is an I/O error reading the URL
 137:    */
 138:   public static AudioFileFormat getAudioFileFormat(URL url)
 139:     throws UnsupportedAudioFileException, IOException
 140:   {
 141:     Iterator<AudioFileReader> i = ServiceFactory.lookupProviders(AudioFileReader.class);
 142:     while (i.hasNext())
 143:       {
 144:         AudioFileReader reader = i.next();
 145:         try
 146:           {
 147:             return reader.getAudioFileFormat(url);
 148:           }
 149:         catch (UnsupportedAudioFileException _)
 150:           {
 151:             // Try the next provider.
 152:           }
 153:       }
 154:     throw new UnsupportedAudioFileException("URL type not recognized");
 155:   }
 156: 
 157:   /**
 158:    * Return an array of all the supported AudioFileFormat types.
 159:    * @return an array of unique types
 160:    */
 161:   public static AudioFileFormat.Type[] getAudioFileTypes()
 162:   {
 163:     HashSet<AudioFileFormat.Type> result
 164:       = new HashSet<AudioFileFormat.Type>();
 165:     Iterator<AudioFileWriter> i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 166:     while (i.hasNext())
 167:       {
 168:         AudioFileWriter writer = i.next();
 169:         AudioFileFormat.Type[] types = writer.getAudioFileTypes();
 170:         for (int j = 0; j < types.length; ++j)
 171:           result.add(types[j]);
 172:       }
 173:     return result.toArray(new AudioFileFormat.Type[result.size()]);
 174:   }
 175: 
 176:   /**
 177:    * Return an array of all the supported AudioFileFormat types which match the
 178:    * given audio input stream
 179:    * @param ais the audio input stream
 180:    * @return an array of unique types
 181:    */
 182:   public static AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream ais)
 183:   {
 184:     HashSet<AudioFileFormat.Type> result
 185:       = new HashSet<AudioFileFormat.Type>();
 186:     Iterator<AudioFileWriter> i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 187:     while (i.hasNext())
 188:       {
 189:         AudioFileWriter writer = i.next();
 190:         AudioFileFormat.Type[] types = writer.getAudioFileTypes(ais);
 191:         for (int j = 0; j < types.length; ++j)
 192:           result.add(types[j]);
 193:       }
 194:     return result.toArray(new AudioFileFormat.Type[result.size()]);
 195:   }
 196: 
 197:   /**
 198:    * Given an audio input stream, this will try to create a new audio input
 199:    * stream whose encoding matches the given target encoding.  If no provider
 200:    * offers this conversion, an exception is thrown.
 201:    * @param targ the target encoding
 202:    * @param ais the original audio stream
 203:    * @return a new audio stream
 204:    * @throws IllegalArgumentException if the conversion cannot be made
 205:    */
 206:   public static AudioInputStream getAudioInputStream(AudioFormat.Encoding targ,
 207:                                                      AudioInputStream ais)
 208:   {
 209:     Iterator<FormatConversionProvider> i =
 210:       ServiceFactory.lookupProviders(FormatConversionProvider.class);
 211:     while (i.hasNext())
 212:       {
 213:         FormatConversionProvider prov = i.next();
 214:         if (! prov.isConversionSupported(targ, ais.getFormat()))
 215:           continue;
 216:         return prov.getAudioInputStream(targ, ais);
 217:       }
 218:     throw new IllegalArgumentException("encoding not supported for stream");
 219:  }
 220: 
 221:   /**
 222:    * Given an audio input stream, this will try to create a new audio input
 223:    * stream whose format matches the given target format.  If no provider
 224:    * offers this conversion, an exception is thrown.
 225:    * @param targ the target format
 226:    * @param ais the original audio stream
 227:    * @return a new audio stream
 228:    * @throws IllegalArgumentException if the conversion cannot be made
 229:    */
 230:   public static AudioInputStream getAudioInputStream(AudioFormat targ,
 231:                                                      AudioInputStream ais)
 232:   {
 233:     Iterator<FormatConversionProvider> i =
 234:       ServiceFactory.lookupProviders(FormatConversionProvider.class);
 235:     while (i.hasNext())
 236:       {
 237:         FormatConversionProvider prov = i.next();
 238:         if (! prov.isConversionSupported(targ, ais.getFormat()))
 239:           continue;
 240:         return prov.getAudioInputStream(targ, ais);
 241:       }
 242:     throw new IllegalArgumentException("format not supported for stream");
 243:    }
 244: 
 245:   /**
 246:    * Return an audio input stream for the file.
 247:    * @param f the file to read
 248:    * @return an audio input stream for the file
 249:    * @throws UnsupportedAudioFileException if the file's audio format is not
 250:    * recognized
 251:    * @throws IOException if there is an error while reading the file
 252:    */
 253:   public static AudioInputStream getAudioInputStream(File f)
 254:     throws UnsupportedAudioFileException, IOException
 255:   {
 256:     Iterator<AudioFileReader> i = ServiceFactory.lookupProviders(AudioFileReader.class);
 257:     while (i.hasNext())
 258:       {
 259:         AudioFileReader reader = i.next();
 260:         try
 261:           {
 262:             return reader.getAudioInputStream(f);
 263:           }
 264:         catch (UnsupportedAudioFileException _)
 265:           {
 266:             // Try the next provider.
 267:           }
 268:       }
 269:     throw new UnsupportedAudioFileException("file type not recognized");
 270:   }
 271: 
 272:   /**
 273:    * Return an audio input stream given an input stream.
 274:    * @param is the input stream
 275:    * @return an audio input stream
 276:    * @throws UnsupportedAudioFileException if the input stream's audio format
 277:    * is not supported by any of the installed providers
 278:    * @throws IOException if there is an error while reading the input stream
 279:    */
 280:   public static AudioInputStream getAudioInputStream(InputStream is)
 281:     throws UnsupportedAudioFileException, IOException
 282:   {
 283:     Iterator<AudioFileReader> i = ServiceFactory.lookupProviders(AudioFileReader.class);
 284:     while (i.hasNext())
 285:       {
 286:         AudioFileReader reader = i.next();
 287:         try
 288:           {
 289:             return reader.getAudioInputStream(is);
 290:           }
 291:         catch (UnsupportedAudioFileException _)
 292:           {
 293:             // Try the next provider.
 294:           }
 295:       }
 296:     throw new UnsupportedAudioFileException("input stream type not recognized");
 297:   }
 298: 
 299:   /**
 300:    * Return an audio input stream for the given URL.
 301:    * @param url the URL
 302:    * @return an audio input stream
 303:    * @throws UnsupportedAudioFileException if the URL's audio format is not
 304:    * supported by any of the installed providers
 305:    * @throws IOException if there is an error while reading the URL
 306:    */
 307:   public static AudioInputStream getAudioInputStream(URL url)
 308:     throws UnsupportedAudioFileException, IOException
 309:   {
 310:     Iterator<AudioFileReader> i = ServiceFactory.lookupProviders(AudioFileReader.class);
 311:     while (i.hasNext())
 312:       {
 313:         AudioFileReader reader = i.next();
 314:         try
 315:           {
 316:             return reader.getAudioInputStream(url);
 317:           }
 318:         catch (UnsupportedAudioFileException _)
 319:           {
 320:             // Try the next provider.
 321:           }
 322:       }
 323:     throw new UnsupportedAudioFileException("URL type not recognized");
 324:   }
 325: 
 326:   /**
 327:    * Return a new clip which can be used for playing back an audio stream.
 328:    * @throws LineUnavailableException if a clip is not available for some
 329:    * reason
 330:    * @throws SecurityException if a clip cannot be made for security reasons
 331:    * @since 1.5
 332:    */
 333:   public static Clip getClip()
 334:     throws LineUnavailableException
 335:   {
 336:     Mixer.Info[] infos = getMixerInfo();
 337:     for (int i = 0; i < infos.length; ++i)
 338:       {
 339:         Mixer mix = getMixer(infos[i]);
 340:         Line[] lines = mix.getSourceLines();
 341:         for (int j = 0; j < lines.length; ++j)
 342:           {
 343:             if (lines[j] instanceof Clip)
 344:               return (Clip) lines[j];
 345:           }
 346:       }
 347:     throw new LineUnavailableException("no Clip available");
 348:   }
 349: 
 350:   /**
 351:    * Return a new clip which can be used for playing back an audio stream.
 352:    * The clip is obtained from the indicated mixer.
 353:    * @param info the mixer to use
 354:    * @throws LineUnavailableException if a clip is not available for some
 355:    * reason
 356:    * @throws SecurityException if a clip cannot be made for security reasons
 357:    * @since 1.5
 358:    */
 359:   public static Clip getClip(Mixer.Info info)
 360:     throws LineUnavailableException
 361:   {
 362:     Mixer mix = getMixer(info);
 363:     Line[] lines = mix.getSourceLines();
 364:     for (int j = 0; j < lines.length; ++j)
 365:       {
 366:         if (lines[j] instanceof Clip)
 367:           return (Clip) lines[j];
 368:       }
 369:     throw new LineUnavailableException("no Clip available");
 370:   }
 371: 
 372:   /**
 373:    * Return a line matching the provided description.  All the providers
 374:    * on the system are searched for a matching line.
 375:    * @param info description of the line
 376:    * @return the matching line
 377:    * @throws LineUnavailableException if no provider supplies a matching line
 378:    */
 379:   public static Line getLine(Line.Info info) throws LineUnavailableException
 380:   {
 381:     Mixer.Info[] infos = getMixerInfo();
 382:     for (int i = 0; i < infos.length; ++i)
 383:       {
 384:         Mixer mix = getMixer(infos[i]);
 385:         try
 386:         {
 387:           return mix.getLine(info);
 388:         }
 389:         catch (LineUnavailableException _)
 390:         {
 391:           // Try the next provider.
 392:         }
 393:       }
 394:     throw new LineUnavailableException("no Clip available");
 395:   }
 396: 
 397:   /**
 398:    * Return a mixer matching the provided description.  All the providers
 399:    * on the system are searched for a matching mixer.
 400:    * @param info description of the mixer
 401:    * @return the matching mixer
 402:    * @throws IllegalArgumentException if no provider supplies a matching mixer
 403:    */
 404:   public static Mixer getMixer(Mixer.Info info)
 405:   {
 406:     Iterator<MixerProvider> i = ServiceFactory.lookupProviders(MixerProvider.class);
 407:     while (i.hasNext())
 408:       {
 409:         MixerProvider prov = i.next();
 410:         if (prov.isMixerSupported(info))
 411:           return prov.getMixer(info);
 412:       }
 413:     throw new IllegalArgumentException("mixer not found");
 414:   }
 415: 
 416:   /**
 417:    * Return an array of descriptions of all the mixers provided on the system.
 418:    */
 419:   public static Mixer.Info[] getMixerInfo()
 420:   {
 421:     HashSet<Mixer.Info> result = new HashSet<Mixer.Info>();
 422:     Iterator<MixerProvider> i = ServiceFactory.lookupProviders(MixerProvider.class);
 423:     while (i.hasNext())
 424:       {
 425:         MixerProvider prov = i.next();
 426:         Mixer.Info[] is = prov.getMixerInfo();
 427:         for (int j = 0; j < is.length; ++j)
 428:           result.add(is[j]);
 429:       }
 430:     return result.toArray(new Mixer.Info[result.size()]);
 431:   }
 432: 
 433:   /**
 434:    * Return a source data line matching the given audio format.
 435:    * @param fmt the audio format
 436:    * @throws LineUnavailableException if no source data line matching
 437:    * this format is available
 438:    * @since 1.5
 439:    */
 440:   public static SourceDataLine getSourceDataLine(AudioFormat fmt)
 441:     throws LineUnavailableException
 442:   {
 443:     DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);
 444:     Mixer.Info[] mixers = getMixerInfo();
 445:     for (int i = 0; i < mixers.length; ++i)
 446:       {
 447:         Mixer mix = getMixer(mixers[i]);
 448:         if (mix.isLineSupported(info))
 449:           return (SourceDataLine) mix.getLine(info);
 450:       }
 451:     throw new LineUnavailableException("source data line not found");
 452:   }
 453: 
 454:   /**
 455:    * Return a target data line matching the given audio format.
 456:    * @param fmt the audio format
 457:    * @throws LineUnavailableException if no target data line matching
 458:    * this format is available
 459:    * @since 1.5
 460:    */
 461:   public static SourceDataLine getSourceDataLine(AudioFormat fmt,
 462:                                                  Mixer.Info mixer)
 463:     throws LineUnavailableException
 464:   {
 465:     DataLine.Info info = new DataLine.Info(SourceDataLine.class, fmt);
 466:     Mixer mix = getMixer(mixer);
 467:     if (mix.isLineSupported(info))
 468:       return (SourceDataLine) mix.getLine(info);
 469:     throw new LineUnavailableException("source data line not found");
 470:   }
 471: 
 472:   /**
 473:    * Return an array of descriptions of all the source lines matching
 474:    * the given line description.
 475:    * @param info description of the lines to match
 476:    */
 477:   public static Line.Info[] getSourceLineInfo(Line.Info info)
 478:   {
 479:     HashSet<Line.Info> result = new HashSet<Line.Info>();
 480:     Mixer.Info[] infos = getMixerInfo();
 481:     for (int i = 0; i < infos.length; ++i)
 482:       {
 483:         Mixer mix = getMixer(infos[i]);
 484:         Line.Info[] srcs = mix.getSourceLineInfo(info);
 485:         for (int j = 0; j < srcs.length; ++j)
 486:           result.add(srcs[j]);
 487:       }
 488:     return result.toArray(new Line.Info[result.size()]);
 489:   }
 490: 
 491:   /**
 492:    * Find and return a target data line matching the given audio format.
 493:    * @param fmt the format to match
 494:    * @throws LineUnavailableException if no matching line was found
 495:    * @since 1.5
 496:    */
 497:   public static TargetDataLine getTargetDataLine(AudioFormat fmt)
 498:     throws LineUnavailableException
 499:   {
 500:     DataLine.Info info = new DataLine.Info(TargetDataLine.class, fmt);
 501:     Mixer.Info[] mixers = getMixerInfo();
 502:     for (int i = 0; i < mixers.length; ++i)
 503:       {
 504:         Mixer mix = getMixer(mixers[i]);
 505:         if (mix.isLineSupported(info))
 506:           return (TargetDataLine) mix.getLine(info);
 507:       }
 508:     throw new LineUnavailableException("target data line not found");
 509:   }
 510: 
 511:   /**
 512:    * Return a target data line matching the given audio format and
 513:    * mixer.
 514:    * @param fmt the audio format
 515:    * @param mixer the mixer description
 516:    * @return a target data line
 517:    * @throws LineUnavailableException if no matching target data line was
 518:    * found
 519:    * @since 1.5
 520:    */
 521:   public static TargetDataLine getTargetDataLine(AudioFormat fmt,
 522:                                                  Mixer.Info mixer)
 523:     throws LineUnavailableException
 524:   {
 525:     DataLine.Info info = new DataLine.Info(TargetDataLine.class, fmt);
 526:     Mixer mix = getMixer(mixer);
 527:     if (mix.isLineSupported(info))
 528:       return (TargetDataLine) mix.getLine(info);
 529:     throw new LineUnavailableException("target data line not found");
 530:   }
 531: 
 532:   /**
 533:    * Given a source encoding, return an array of all target encodings to which
 534:    * data in this form can be converted.
 535:    * @param source the source encoding
 536:    */
 537:   public static AudioFormat.Encoding[] getTargetEncodings(AudioFormat.Encoding source)
 538:   {
 539:     HashSet<AudioFormat.Encoding> result
 540:       = new HashSet<AudioFormat.Encoding>();
 541:     Iterator<FormatConversionProvider> i =
 542:       ServiceFactory.lookupProviders(FormatConversionProvider.class);
 543:     while (i.hasNext())
 544:       {
 545:         FormatConversionProvider prov = i.next();
 546:         if (! prov.isSourceEncodingSupported(source))
 547:           continue;
 548:         AudioFormat.Encoding[] es = prov.getTargetEncodings();
 549:         for (int j = 0; j < es.length; ++j)
 550:           result.add(es[j]);
 551:       }
 552:     return result.toArray(new AudioFormat.Encoding[result.size()]);
 553:   }
 554: 
 555:   /**
 556:    * Given a source format, return an array of all the target encodings to
 557:    * which data in this format can be converted.
 558:    * @param source the source format
 559:    */
 560:   public static AudioFormat.Encoding[] getTargetEncodings(AudioFormat source)
 561:   {
 562:     HashSet<AudioFormat.Encoding> result
 563:       = new HashSet<AudioFormat.Encoding>();
 564:     Iterator<FormatConversionProvider> i =
 565:       ServiceFactory.lookupProviders(FormatConversionProvider.class);
 566:     while (i.hasNext())
 567:       {
 568:         FormatConversionProvider prov = i.next();
 569:         AudioFormat.Encoding[] es = prov.getTargetEncodings(source);
 570:         for (int j = 0; j < es.length; ++j)
 571:           result.add(es[j]);
 572:       }
 573:     return result.toArray(new AudioFormat.Encoding[result.size()]);
 574:   }
 575: 
 576:   /**
 577:    * Given a target encoding and a source audio format, return an array of all
 578:    * matching audio formats to which data in this source format can be converted.
 579:    * @param encoding the target encoding
 580:    * @param sourceFmt the source format
 581:    */
 582:   public static AudioFormat[] getTargetFormats(AudioFormat.Encoding encoding,
 583:                                                AudioFormat sourceFmt)
 584:   {
 585:     HashSet<AudioFormat> result = new HashSet<AudioFormat>();
 586:     Iterator<FormatConversionProvider> i =
 587:       ServiceFactory.lookupProviders(FormatConversionProvider.class);
 588:     while (i.hasNext())
 589:       {
 590:         FormatConversionProvider prov = i.next();
 591:         AudioFormat[] es = prov.getTargetFormats(encoding, sourceFmt);
 592:         for (int j = 0; j < es.length; ++j)
 593:           result.add(es[j]);
 594:       }
 595:     return result.toArray(new AudioFormat[result.size()]);
 596:   }
 597: 
 598:   /**
 599:    * Given a line description, return an array of descriptions of all
 600:    * the matching target lines.
 601:    * @param info the line description
 602:    */
 603:   public static Line.Info[] getTargetLineInfo(Line.Info info)
 604:   {
 605:     HashSet<Line.Info> result = new HashSet<Line.Info>();
 606:     Mixer.Info[] infos = getMixerInfo();
 607:     for (int i = 0; i < infos.length; ++i)
 608:       {
 609:         Mixer mix = getMixer(infos[i]);
 610:         Line.Info[] targs = mix.getTargetLineInfo(info);
 611:         for (int j = 0; j < targs.length; ++j)
 612:           result.add(targs[j]);
 613:       }
 614:     return result.toArray(new Line.Info[result.size()]);
 615:   }
 616: 
 617:   /**
 618:    * Return true if the currently installed providers are able to
 619:    * convert data from the given source format to the given target encoding.
 620:    * @param targ the target encoding
 621:    * @param source the source format
 622:    */
 623:   public static boolean isConversionSupported(AudioFormat.Encoding targ,
 624:                                               AudioFormat source)
 625:   {
 626:     Iterator<FormatConversionProvider> i
 627:       = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 628:     while (i.hasNext())
 629:       {
 630:         FormatConversionProvider prov = i.next();
 631:         if (prov.isConversionSupported(targ, source))
 632:           return true;
 633:       }
 634:     return false;
 635:   }
 636: 
 637:   /**
 638:    * Return true if the currently installed providers are able to convert
 639:    * the given source format to the given target format.
 640:    * @param targ the target format
 641:    * @param source the source format
 642:    */
 643:   public static boolean isConversionSupported(AudioFormat targ,
 644:                                               AudioFormat source)
 645:   {
 646:     Iterator<FormatConversionProvider> i
 647:       = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 648:     while (i.hasNext())
 649:       {
 650:         FormatConversionProvider prov = i.next();
 651:         if (prov.isConversionSupported(targ, source))
 652:           return true;
 653:       }
 654:     return false;
 655:   }
 656: 
 657:   private static boolean isFileTypeSupported(AudioFileFormat.Type[] types,
 658:                                              AudioFileFormat.Type type)
 659:   {
 660:     for (int i = 0; i < types.length; ++i)
 661:       {
 662:         if (types[i].equals(type))
 663:           return true;
 664:       }
 665:     return false;
 666:   }
 667: 
 668:   /**
 669:    * Return true if the given audio file format is supported by one of
 670:    * the providers installed on the system.
 671:    * @param type the audio file format type
 672:    */
 673:   public static boolean isFileTypeSupported(AudioFileFormat.Type type)
 674:   {
 675:     return isFileTypeSupported(getAudioFileTypes(), type);
 676:   }
 677: 
 678:   /**
 679:    * Return true if the given audio file format is supported for the
 680:    * given audio input stream by one of the providers installed on the
 681:    * system.
 682:    * @param type the audio file format type
 683:    * @param ais the audio input stream
 684:    */
 685:   public static boolean isFileTypeSupported(AudioFileFormat.Type type,
 686:                                             AudioInputStream ais)
 687:   {
 688:     return isFileTypeSupported(getAudioFileTypes(ais), type);
 689:   }
 690: 
 691:   /**
 692:    * Return true if some provider on the system supplies a line
 693:    * matching the argument.
 694:    * @param info the line to match
 695:    */
 696:   public static boolean isLineSupported(Line.Info info)
 697:   {
 698:     Mixer.Info[] infos = getMixerInfo();
 699:     for (int i = 0; i < infos.length; ++i)
 700:       {
 701:         if (getMixer(infos[i]).isLineSupported(info))
 702:           return true;
 703:       }
 704:     return false;
 705:   }
 706: 
 707:   /**
 708:    * Write an audio input stream to the given file, using the specified
 709:    * audio file format.  All the providers installed on the system will
 710:    * be searched to find one that supports this operation.
 711:    * @param ais the audio input stream to write
 712:    * @param type the desired audio file format type
 713:    * @param out the file to write to
 714:    * @return the number of bytes written
 715:    * @throws IOException if an I/O error occurs while writing
 716:    * @throws IllegalArgumentException if the file type is not supported
 717:    */
 718:   public static int write(AudioInputStream ais, AudioFileFormat.Type type,
 719:                           File out)
 720:     throws IOException
 721:   {
 722:     Iterator<AudioFileWriter> i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 723:     while (i.hasNext())
 724:       {
 725:         AudioFileWriter w = i.next();
 726:         if (w.isFileTypeSupported(type, ais))
 727:           return w.write(ais, type, out);
 728:       }
 729:     throw new IllegalArgumentException("file type not supported by system");
 730:   }
 731: 
 732:   /**
 733:    * Write an audio input stream to the given output stream, using the
 734:    * specified audio file format.  All the providers installed on the
 735:    * system will be searched to find one that supports this operation.
 736:    * @param ais the audio input stream to write
 737:    * @param type the desired audio file format type
 738:    * @param os the output stream to write to
 739:    * @return the number of bytes written
 740:    * @throws IOException if an I/O error occurs while writing
 741:    * @throws IllegalArgumentException if the file type is not supported
 742:    */
 743:   public static int write(AudioInputStream ais, AudioFileFormat.Type type,
 744:                           OutputStream os)
 745:     throws IOException
 746:   {
 747:     Iterator<AudioFileWriter> i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 748:     while (i.hasNext())
 749:       {
 750:         AudioFileWriter w = i.next();
 751:         if (w.isFileTypeSupported(type, ais))
 752:           return w.write(ais, type, os);
 753:       }
 754:     throw new IllegalArgumentException("file type not supported by system");
 755:   }
 756: }