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