8133677: Specification of AudioFileReader should be clarifed
authorserb
Wed, 02 Sep 2015 16:13:14 +0300
changeset 32663 1279321775f1
parent 32497 64edba808ec4
child 32664 dbe7dd1f80e3
8133677: Specification of AudioFileReader should be clarifed Reviewed-by: prr, amenkov
jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java
jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java
jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java
jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java
jdk/test/javax/sound/sampled/FileReader/RepeatedFormatReader.java
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java	Tue Sep 01 11:03:43 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java	Wed Sep 02 16:13:14 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,8 @@
 
 package com.sun.media.sound;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URL;
 
 import javax.sound.midi.InvalidMidiDataException;
 import javax.sound.midi.MetaMessage;
@@ -44,28 +42,27 @@
 import javax.sound.sampled.AudioFormat;
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.UnsupportedAudioFileException;
-import javax.sound.sampled.spi.AudioFileReader;
 
 /**
  * MIDI File Audio Renderer/Reader.
  *
  * @author Karl Helgason
  */
-public final class SoftMidiAudioFileReader extends AudioFileReader {
+public final class SoftMidiAudioFileReader extends SunFileReader {
+
+    private static final Type MIDI = new Type("MIDI", "mid");
 
-    public static final Type MIDI = new Type("MIDI", "mid");
-    private static AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+    private static final AudioFormat format = new AudioFormat(44100, 16, 2,
+                                                              true, false);
 
-    public AudioFileFormat getAudioFileFormat(Sequence seq)
-            throws UnsupportedAudioFileException, IOException {
-
+    private static AudioFileFormat getAudioFileFormat(final Sequence seq) {
         long totallen = seq.getMicrosecondLength() / 1000000;
         long len = (long) (format.getFrameRate() * (totallen + 4));
         return new AudioFileFormat(MIDI, format, (int) len);
     }
 
-    public AudioInputStream getAudioInputStream(Sequence seq)
-            throws UnsupportedAudioFileException, IOException {
+    private AudioInputStream getAudioInputStream(final Sequence seq)
+            throws InvalidMidiDataException {
         AudioSynthesizer synth = (AudioSynthesizer) new SoftSynthesizer();
         AudioInputStream stream;
         Receiver recv;
@@ -73,7 +70,7 @@
             stream = synth.openStream(format, null);
             recv = synth.getReceiver();
         } catch (MidiUnavailableException e) {
-            throw new IOException(e.toString());
+            throw new InvalidMidiDataException(e.toString());
         }
         float divtype = seq.getDivisionType();
         Track[] tracks = seq.getTracks();
@@ -111,7 +108,7 @@
                     if (((MetaMessage) msg).getType() == 0x51) {
                         byte[] data = ((MetaMessage) msg).getData();
                         if (data.length < 3) {
-                            throw new UnsupportedAudioFileException();
+                            throw new InvalidMidiDataException();
                         }
                         mpq = ((data[0] & 0xff) << 16)
                                 | ((data[1] & 0xff) << 8) | (data[2] & 0xff);
@@ -128,91 +125,25 @@
         return stream;
     }
 
-    public AudioInputStream getAudioInputStream(InputStream inputstream)
+    @Override
+    public AudioInputStream getAudioInputStream(final InputStream stream)
             throws UnsupportedAudioFileException, IOException {
-
-        inputstream.mark(200);
-        Sequence seq;
+        stream.mark(200);
         try {
-            seq = MidiSystem.getSequence(inputstream);
-        } catch (InvalidMidiDataException e) {
-            inputstream.reset();
-            throw new UnsupportedAudioFileException();
-        } catch (IOException e) {
-            inputstream.reset();
+            return getAudioInputStream(MidiSystem.getSequence(stream));
+        } catch (final InvalidMidiDataException ignored) {
+            stream.reset();
             throw new UnsupportedAudioFileException();
         }
-        return getAudioInputStream(seq);
-    }
-
-    public AudioFileFormat getAudioFileFormat(URL url)
-            throws UnsupportedAudioFileException, IOException {
-        Sequence seq;
-        try {
-            seq = MidiSystem.getSequence(url);
-        } catch (InvalidMidiDataException e) {
-            throw new UnsupportedAudioFileException();
-        } catch (IOException e) {
-            throw new UnsupportedAudioFileException();
-        }
-        return getAudioFileFormat(seq);
-    }
-
-    public AudioFileFormat getAudioFileFormat(File file)
-            throws UnsupportedAudioFileException, IOException {
-        Sequence seq;
-        try {
-            seq = MidiSystem.getSequence(file);
-        } catch (InvalidMidiDataException e) {
-            throw new UnsupportedAudioFileException();
-        } catch (IOException e) {
-            throw new UnsupportedAudioFileException();
-        }
-        return getAudioFileFormat(seq);
     }
 
-    public AudioInputStream getAudioInputStream(URL url)
+    @Override
+    AudioFileFormat getAudioFileFormatImpl(final InputStream stream)
             throws UnsupportedAudioFileException, IOException {
-        Sequence seq;
         try {
-            seq = MidiSystem.getSequence(url);
-        } catch (InvalidMidiDataException e) {
-            throw new UnsupportedAudioFileException();
-        } catch (IOException e) {
+            return getAudioFileFormat(MidiSystem.getSequence(stream));
+        } catch (final InvalidMidiDataException ignored) {
             throw new UnsupportedAudioFileException();
         }
-        return getAudioInputStream(seq);
-    }
-
-    public AudioInputStream getAudioInputStream(File file)
-            throws UnsupportedAudioFileException, IOException {
-        if (!file.getName().toLowerCase().endsWith(".mid"))
-            throw new UnsupportedAudioFileException();
-        Sequence seq;
-        try {
-            seq = MidiSystem.getSequence(file);
-        } catch (InvalidMidiDataException e) {
-            throw new UnsupportedAudioFileException();
-        } catch (IOException e) {
-            throw new UnsupportedAudioFileException();
-        }
-        return getAudioInputStream(seq);
-    }
-
-    public AudioFileFormat getAudioFileFormat(InputStream inputstream)
-            throws UnsupportedAudioFileException, IOException {
-
-        inputstream.mark(200);
-        Sequence seq;
-        try {
-            seq = MidiSystem.getSequence(inputstream);
-        } catch (InvalidMidiDataException e) {
-            inputstream.reset();
-            throw new UnsupportedAudioFileException();
-        } catch (IOException e) {
-            inputstream.reset();
-            throw new UnsupportedAudioFileException();
-        }
-        return getAudioFileFormat(seq);
     }
 }
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java	Tue Sep 01 11:03:43 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunFileReader.java	Wed Sep 02 16:13:14 2015 +0300
@@ -52,10 +52,6 @@
         try {
             return getAudioFileFormatImpl(stream);
         } finally {
-            // According to specification the following is not strictly
-            // necessary, if we got correct format. But it was implemented like
-            // that in 1.3.0 - 1.8. So I leave it as it was, but it seems
-            // specification should be updated.
             stream.reset();
         }
     }
--- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java	Tue Sep 01 11:03:43 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java	Wed Sep 02 16:13:14 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -912,9 +912,9 @@
      * must point to valid audio file data. The implementation of this method
      * may require multiple parsers to examine the stream to determine whether
      * they support it. These parsers must be able to mark the stream, read
-     * enough data to determine whether they support the stream, and, if not,
-     * reset the stream's read pointer to its original position. If the input
-     * stream does not support these operations, this method may fail with an
+     * enough data to determine whether they support the stream, and reset the
+     * stream's read pointer to its original position. If the input stream does
+     * not support these operations, this method may fail with an
      * {@code IOException}.
      *
      * @param  stream the input stream from which file format information should
@@ -1025,9 +1025,9 @@
      * must point to valid audio file data. The implementation of this method
      * may require multiple parsers to examine the stream to determine whether
      * they support it. These parsers must be able to mark the stream, read
-     * enough data to determine whether they support the stream, and, if not,
-     * reset the stream's read pointer to its original position. If the input
-     * stream does not support these operation, this method may fail with an
+     * enough data to determine whether they support the stream, and reset the
+     * stream's read pointer to its original position. If the input stream does
+     * not support these operation, this method may fail with an
      * {@code IOException}.
      *
      * @param  stream the input stream from which the {@code AudioInputStream}
--- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java	Tue Sep 01 11:03:43 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java	Wed Sep 02 16:13:14 2015 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,9 +49,9 @@
      * must point to valid audio file data. In general, audio file readers may
      * need to read some data from the stream before determining whether they
      * support it. These parsers must be able to mark the stream, read enough
-     * data to determine whether they support the stream, and, if not, reset the
-     * stream's read pointer to its original position. If the input stream does
-     * not support this, this method may fail with an {@code IOException}.
+     * data to determine whether they support the stream, and reset the stream's
+     * read pointer to its original position. If the input stream does not
+     * support this, this method may fail with an {@code IOException}.
      *
      * @param  stream the input stream from which file format information should
      *         be extracted
@@ -101,9 +101,9 @@
      * must point to valid audio file data. In general, audio file readers may
      * need to read some data from the stream before determining whether they
      * support it. These parsers must be able to mark the stream, read enough
-     * data to determine whether they support the stream, and, if not, reset the
-     * stream's read pointer to its original position. If the input stream does
-     * not support this, this method may fail with an {@code IOException}.
+     * data to determine whether they support the stream, and reset the stream's
+     * read pointer to its original position. If the input stream does not
+     * support this, this method may fail with an {@code IOException}.
      *
      * @param  stream the input stream from which the {@code AudioInputStream}
      *         should be constructed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/FileReader/RepeatedFormatReader.java	Wed Sep 02 16:13:14 2015 +0300
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+
+/**
+ * @test
+ * @bug 8133677
+ * @summary Subsequent read from the same stream should work
+ */
+public final class RepeatedFormatReader {
+
+    // Stubs
+
+    private static byte[] headerMIDI = {0x4d, 0x54, 0x68, 0x64, // MThd
+                                        0, 0, 0, 6, // read header length
+                                        0, 0, // type
+                                        0, 0, // numtracks
+                                        0, 1, // timing
+    };
+
+    private static byte[] headerAU = {0x2e, 0x73, 0x6e, 0x64, // AU_SUN_MAGIC
+                                      0, 0, 0, 0, // headerSize
+                                      0, 0, 0, 0, // dataSize
+                                      0, 0, 0, 1, // encoding
+                                      0, 0, 0, 0, // sampleRate
+                                      0, 0, 0, 1  // channels
+    };
+
+    private static byte[] headerWAV = {0x52, 0x49, 0x46, 0x46, // RIFF_MAGIC
+                                       1, 1, 1, 1, // fileLength
+                                       0x57, 0x41, 0x56, 0x45, //  waveMagic
+                                       0x66, 0x6d, 0x74, 0x20, // FMT_MAGIC
+                                       3, 0, 0, 0, // length
+                                       1, 0, // wav_type  WAVE_FORMAT_PCM
+                                       0, 1, // channels
+                                       0, 0, 0, 0, // sampleRate
+                                       0, 0, 0, 0, // avgBytesPerSec
+                                       0, 0, // blockAlign
+                                       1, 0, // sampleSizeInBits
+                                       0x64, 0x61, 0x74, 0x61, // DATA_MAGIC
+                                       0, 0, 0, 0, // dataLength
+    };
+
+    private static final byte[][] data = {headerMIDI, headerAU, headerWAV};
+
+    public static void main(final String[] args)
+            throws IOException, UnsupportedAudioFileException {
+        for (final byte[] bytes : data) {
+            test(bytes);
+        }
+    }
+
+    private static void test(final byte[] buffer)
+            throws IOException, UnsupportedAudioFileException {
+        final InputStream is = new ByteArrayInputStream(buffer);
+        for (int i = 0; i < 10; ++i) {
+            AudioSystem.getAudioFileFormat(is);
+        }
+    }
+}