/* * Copyright (c) 2003, 2016, 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.File; import java.io.IOException; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; /** * @test * @bug 4834461 * @summary Applet hang when you load it during sound card is in use * @run main/manual PlaySine */ public class PlaySine { static int sampleRate = 8000; static double frequency = 2000.0; static double RAD = 2.0 * Math.PI; static byte[] audioData = new byte[sampleRate/2]; static SourceDataLine source; static Mixer mixer = null; static AudioInputStream ais = null; static AudioFormat audioFormat; static String filename; public static void constructAIS() { try { ais = AudioSystem.getAudioInputStream(new File(filename)); } catch (Exception e) { println("ERROR: could not open "+filename+": "+e.getMessage()); } } public static void print(String s) { System.out.print(s); } public static void println(String s) { System.out.println(s); } public static void key() { println(""); print("Press ENTER to continue..."); try { System.in.read(); } catch (IOException ioe) { } } static int audioLen = -1; static int audioOffset = -1; public static void writeData() { if (audioLen == -1) { audioLen = audioData.length; } if (audioOffset < 0) { audioOffset = audioLen; } try { if (audioOffset >= audioLen) { audioOffset = 0; if (ais!=null) { do { audioLen = ais.read(audioData, 0, audioData.length); if (audioLen < 0) { constructAIS(); } } while (audioLen < 0); } } int toWrite = audioLen - audioOffset; int written = source.write(audioData, audioOffset, toWrite); audioOffset+=written; } catch (Exception e) { e.printStackTrace(); } } public static int play(boolean shouldPlay) { int res = 0; DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat); try { println("Getting line from mixer..."); source = (SourceDataLine) mixer.getLine(info); println("Opening line..."); println(" -- if the program is hanging here, kill the process that has blocks the audio device now."); source.open(audioFormat); println("Starting line..."); source.start(); println("Writing audio data for 1 second..."); long startTime = System.currentTimeMillis(); while (System.currentTimeMillis() - startTime < 1000) { writeData(); Thread.sleep(100); } res = 1; } catch (IllegalArgumentException iae) { println("IllegalArgumentException: "+iae.getMessage()); println("Sound device cannot handle this audio format."); println("ERROR: Test environment not correctly set up."); if (source!=null) { source.close(); } return 3; } catch (LineUnavailableException lue) { println("LineUnavailableException: "+lue.getMessage()); if (shouldPlay) { println("ERROR: the line should be available now!."); println(" Verify that you killed the other audio process."); } else { println("Correct behavior! the bug is fixed."); } res = 2; } catch (Exception e) { println("Unexpected Exception: "+e.toString()); } if (source != null) { println("Draining..."); try { source.drain(); } catch (NullPointerException npe) { println("(NullPointerException: bug fixed in J2SE 1.4.2"); } println("Stopping..."); source.stop(); println("Closing..."); source.close(); source = null; } return res; } public static void main(String[] args) throws Exception { println("This is an interactive test. You can run it with a filename as argument"); println("It is only meant to be run on linux, with the (old) OSS kernel drivers (/dev/dsp)"); println("This test should not be run on systems with ALSA installed, or kernel 2.6 or higher."); println(""); println("The test verifies that Java Sound fails correctly if another process is blocking"); println("the audio device."); println(""); println("Checking sanity..."); Mixer.Info[] mixers=null; mixers = AudioSystem.getMixerInfo(); for (int i=0; i<mixers.length; i++) { try { Mixer thisMixer = AudioSystem.getMixer(mixers[i]); String mixerName = thisMixer.getMixerInfo().getName(); if (mixerName.indexOf("Java Sound")>=0 && mixerName.indexOf("Engine")>=0) { mixer = thisMixer; break; } } catch (Exception e) { e.printStackTrace(); } } if (mixer == null) { if (mixers.length==0) { System.out.println("ERROR: No mixers available!"); } else { println("ERROR: Java Sound Engine could not be found."); } println("Cannot run this test."); return; } println(" ...using mixer "+mixer.getMixerInfo()); String osname = System.getProperty("os.name"); if ((osname == null) || (osname.toLowerCase().indexOf("linux")<0)) { println("ERROR: not running on linux (you are running on "+osname+")"); return; } println(" ...running on "+osname); println(" ...sanity test OK."); filename = null; if (args.length>0) { File f = new File(args[0]); if (f.exists()) { filename = args[0]; println("Opening "+filename); constructAIS(); if (ais!=null) { audioFormat = ais.getFormat(); } } } if (ais == null) { println("Using self-generated sine wave for playback"); audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true); for (int i=0; i<audioData.length; i++) { audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0); } } println(""); println("Now, on a second console, run the following command:"); println(" cat - < /dev/zero > /dev/dsp"); key(); println("After you press ENTER now, the mixer will be opened."); println("There are 3 possible cases that can occur:"); println("1) you'll hear a sine wave"); println(" -> you are running with mixing OSS drivers. "); println(" Some soundcards only provide mixing OSS drivers."); println(" Test environment not valid. "); println(" Repeat on another machine where you can reproduce the bug first."); println("2) this program stops doing anything after 'Opening line...'"); println(" -> this is the bug."); println(" Kill the command on the other console with Ctrl-C, this program"); println(" should continue working then."); println("3) this program reports a LineUnavailableException"); println(" -> bug is fixed."); println(" OR you run with non-blocking OSS drivers."); println(" make sure that you can reproduce this bug first with e.g. J2SE 1.4.1"); key(); int playedFirst = play(false); int playedSecond = 0; if (playedFirst == 2) { println(""); println("Now kill the other process with Ctrl-C."); println("After that, this program should be able to play "); println("the sine wave without problems."); key(); playedSecond = play(true); } println(""); if (playedFirst == 1) { println("Test FAILED."); } else if (playedFirst == 2 && playedSecond == 1) { println("Test SUCCESSFUL"); } else { println("Test not failed (but not successful either...)."); } } }