Source for javax.sound.sampled.AudioSystem

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