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<AudioFileFormat.Type> result
 164:       = new HashSet<AudioFileFormat.Type>();
 165:     Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 166:     while (i.hasNext())
 167:       {
 168:         AudioFileWriter writer = (AudioFileWriter) 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 i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 187:     while (i.hasNext())
 188:       {
 189:         AudioFileWriter writer = (AudioFileWriter) 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 i = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 210:     while (i.hasNext())
 211:       {
 212:         FormatConversionProvider prov = (FormatConversionProvider) i.next();
 213:         if (! prov.isConversionSupported(targ, ais.getFormat()))
 214:           continue;
 215:         return prov.getAudioInputStream(targ, ais);
 216:       }
 217:     throw new IllegalArgumentException("encoding not supported for stream");
 218:  }
 219: 
 220:   /**
 221:    * Given an audio input stream, this will try to create a new audio input
 222:    * stream whose format matches the given target format.  If no provider
 223:    * offers this conversion, an exception is thrown. 
 224:    * @param targ the target format
 225:    * @param ais the original audio stream
 226:    * @return a new audio stream
 227:    * @throws IllegalArgumentException if the conversion cannot be made
 228:    */
 229:   public static AudioInputStream getAudioInputStream(AudioFormat targ,
 230:                              AudioInputStream ais)
 231:   {
 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<Mixer.Info> result = new HashSet<Mixer.Info>();
 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 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<Line.Info> result = new HashSet<Line.Info>();
 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 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<AudioFormat.Encoding> result
 538:       = new HashSet<AudioFormat.Encoding>();
 539:     Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 540:     while (i.hasNext())
 541:       {
 542:         FormatConversionProvider prov = (FormatConversionProvider) i.next();
 543:         if (! prov.isSourceEncodingSupported(source))
 544:           continue;
 545:         AudioFormat.Encoding[] es = prov.getTargetEncodings();
 546:         for (int j = 0; j < es.length; ++j)
 547:           result.add(es[j]);
 548:       }
 549:     return result.toArray(new AudioFormat.Encoding[result.size()]);
 550:   }
 551: 
 552:   /**
 553:    * Given a source format, return an array of all the target encodings to
 554:    * which data in this format can be converted.
 555:    * @param source the source format
 556:    */
 557:   public static AudioFormat.Encoding[] getTargetEncodings(AudioFormat source)
 558:   {
 559:     HashSet<AudioFormat.Encoding> result
 560:       = new HashSet<AudioFormat.Encoding>();
 561:     Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 562:     while (i.hasNext())
 563:       {
 564:         FormatConversionProvider prov = (FormatConversionProvider) i.next();
 565:         AudioFormat.Encoding[] es = prov.getTargetEncodings(source);
 566:         for (int j = 0; j < es.length; ++j)
 567:           result.add(es[j]);
 568:       }
 569:     return result.toArray(new AudioFormat.Encoding[result.size()]);
 570:   }
 571: 
 572:   /**
 573:    * Given a target encoding and a source audio format, return an array of all
 574:    * matching audio formats to which data in this source format can be converted. 
 575:    * @param encoding the target encoding
 576:    * @param sourceFmt the source format
 577:    */
 578:   public static AudioFormat[] getTargetFormats(AudioFormat.Encoding encoding,
 579:                            AudioFormat sourceFmt)
 580:   {
 581:     HashSet<AudioFormat> result = new HashSet<AudioFormat>();
 582:     Iterator i = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 583:     while (i.hasNext())
 584:       {
 585:         FormatConversionProvider prov = (FormatConversionProvider) i.next();
 586:         AudioFormat[] es = prov.getTargetFormats(encoding, sourceFmt);
 587:         for (int j = 0; j < es.length; ++j)
 588:           result.add(es[j]);
 589:       }
 590:     return result.toArray(new AudioFormat[result.size()]);
 591:   }
 592: 
 593:   /**
 594:    * Given a line description, return an array of descriptions of all
 595:    * the matching target lines.
 596:    * @param info the line description
 597:    */
 598:   public static Line.Info[] getTargetLineInfo(Line.Info info)
 599:   {
 600:     HashSet<Line.Info> result = new HashSet<Line.Info>();
 601:     Mixer.Info[] infos = getMixerInfo();
 602:     for (int i = 0; i < infos.length; ++i)
 603:       {
 604:         Mixer mix = getMixer(infos[i]);
 605:         Line.Info[] targs = mix.getTargetLineInfo(info);
 606:         for (int j = 0; j < targs.length; ++j)
 607:           result.add(targs[j]);
 608:       }
 609:     return result.toArray(new Line.Info[result.size()]);
 610:   }
 611: 
 612:   /**
 613:    * Return true if the currently installed providers are able to
 614:    * convert data from the given source format to the given target encoding.
 615:    * @param targ the target encoding
 616:    * @param source the source format
 617:    */
 618:   public static boolean isConversionSupported(AudioFormat.Encoding targ,
 619:                           AudioFormat source)
 620:   {
 621:     Iterator i 
 622:       = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 623:     while (i.hasNext())
 624:       {
 625:         FormatConversionProvider prov = (FormatConversionProvider) i.next();
 626:         if (prov.isConversionSupported(targ, source))
 627:           return true;
 628:       }
 629:     return false;
 630:   }
 631: 
 632:   /**
 633:    * Return true if the currently installed providers are able to convert
 634:    * the given source format to the given target format.
 635:    * @param targ the target format
 636:    * @param source the source format
 637:    */
 638:   public static boolean isConversionSupported(AudioFormat targ,
 639:                           AudioFormat source)
 640:   {
 641:     Iterator i 
 642:       = ServiceFactory.lookupProviders(FormatConversionProvider.class);
 643:     while (i.hasNext())
 644:       {
 645:         FormatConversionProvider prov = (FormatConversionProvider) i.next();
 646:         if (prov.isConversionSupported(targ, source))
 647:           return true;
 648:       }
 649:     return false;
 650:   }
 651: 
 652:   private static boolean isFileTypeSupported(AudioFileFormat.Type[] types,
 653:                                              AudioFileFormat.Type type)
 654:   {
 655:     for (int i = 0; i < types.length; ++i)
 656:       {
 657:         if (types[i].equals(type))
 658:           return true;
 659:       }
 660:     return false;
 661:   }
 662: 
 663:   /**
 664:    * Return true if the given audio file format is supported by one of
 665:    * the providers installed on the system.
 666:    * @param type the audio file format type
 667:    */
 668:   public static boolean isFileTypeSupported(AudioFileFormat.Type type)
 669:   {
 670:     return isFileTypeSupported(getAudioFileTypes(), type);
 671:   }
 672: 
 673:   /**
 674:    * Return true if the given audio file format is supported for the
 675:    * given audio input stream by one of the providers installed on the 
 676:    * system.
 677:    * @param type the audio file format type
 678:    * @param ais the audio input stream
 679:    */
 680:   public static boolean isFileTypeSupported(AudioFileFormat.Type type,
 681:                         AudioInputStream ais)
 682:   {
 683:     return isFileTypeSupported(getAudioFileTypes(ais), type);
 684:   }
 685: 
 686:   /**
 687:    * Return true if some provider on the system supplies a line
 688:    * matching the argument. 
 689:    * @param info the line to match
 690:    */
 691:   public static boolean isLineSupported(Line.Info info)
 692:   {
 693:     Mixer.Info[] infos = getMixerInfo();
 694:     for (int i = 0; i < infos.length; ++i)
 695:       {
 696:         if (getMixer(infos[i]).isLineSupported(info))
 697:           return true;
 698:       }
 699:     return false;
 700:   }
 701: 
 702:   /**
 703:    * Write an audio input stream to the given file, using the specified
 704:    * audio file format.  All the providers installed on the system will
 705:    * be searched to find one that supports this operation.
 706:    * @param ais the audio input stream to write
 707:    * @param type the desired audio file format type
 708:    * @param out the file to write to
 709:    * @return the number of bytes written
 710:    * @throws IOException if an I/O error occurs while writing
 711:    * @throws IllegalArgumentException if the file type is not supported
 712:    */
 713:   public static int write(AudioInputStream ais, AudioFileFormat.Type type,
 714:               File out)
 715:     throws IOException
 716:   {
 717:     Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 718:     while (i.hasNext())
 719:       {
 720:         AudioFileWriter w = (AudioFileWriter) i.next();
 721:         if (w.isFileTypeSupported(type, ais))
 722:           return w.write(ais, type, out);
 723:       }
 724:     throw new IllegalArgumentException("file type not supported by system");
 725:   }
 726: 
 727:   /**
 728:    * Write an audio input stream to the given output stream, using the
 729:    * specified audio file format.  All the providers installed on the
 730:    * system will be searched to find one that supports this operation.
 731:    * @param ais the audio input stream to write
 732:    * @param type the desired audio file format type
 733:    * @param os the output stream to write to
 734:    * @return the number of bytes written
 735:    * @throws IOException if an I/O error occurs while writing
 736:    * @throws IllegalArgumentException if the file type is not supported
 737:    */
 738:   public static int write(AudioInputStream ais, AudioFileFormat.Type type,
 739:               OutputStream os)
 740:     throws IOException
 741:   {
 742:     Iterator i = ServiceFactory.lookupProviders(AudioFileWriter.class);
 743:     while (i.hasNext())
 744:       {
 745:         AudioFileWriter w = (AudioFileWriter) i.next();
 746:         if (w.isFileTypeSupported(type, ais))
 747:           return w.write(ais, type, os);
 748:       }
 749:     throw new IllegalArgumentException("file type not supported by system");
 750:   }
 751: }