< prev index next >

src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java

Print this page

        

*** 27,65 **** import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Vector; ! import javax.sound.sampled.*; // IDEA: // Use java.util.concurrent.Semaphore, // java.util.concurrent.locks.ReentrantLock and other new classes/methods // to improve this class's thread safety. - /** ! * A Mixer which provides direct access to audio devices * * @author Florian Bomers */ final class DirectAudioDevice extends AbstractMixer { - // CONSTANTS private static final int CLIP_BUFFER_TIME = 1000; // in milliseconds private static final int DEFAULT_LINE_BUFFER_TIME = 500; // in milliseconds - // INSTANCE VARIABLES - - /** number of opened lines */ - private int deviceCountOpened = 0; - - /** number of started lines */ - private int deviceCountStarted = 0; - - // CONSTRUCTOR DirectAudioDevice(DirectAudioDeviceProvider.DirectAudioDeviceInfo portMixerInfo) { // pass in Line.Info, mixer, controls super(portMixerInfo, // Mixer.Info null, // Control[] null, // Line.Info[] sourceLineInfo --- 27,65 ---- import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Vector; ! import javax.sound.sampled.AudioFormat; ! import javax.sound.sampled.AudioInputStream; ! import javax.sound.sampled.AudioSystem; ! import javax.sound.sampled.BooleanControl; ! import javax.sound.sampled.Clip; ! import javax.sound.sampled.Control; ! import javax.sound.sampled.DataLine; ! import javax.sound.sampled.FloatControl; ! import javax.sound.sampled.Line; ! import javax.sound.sampled.LineUnavailableException; ! import javax.sound.sampled.SourceDataLine; ! import javax.sound.sampled.TargetDataLine; // IDEA: // Use java.util.concurrent.Semaphore, // java.util.concurrent.locks.ReentrantLock and other new classes/methods // to improve this class's thread safety. /** ! * A Mixer which provides direct access to audio devices. * * @author Florian Bomers */ final class DirectAudioDevice extends AbstractMixer { private static final int CLIP_BUFFER_TIME = 1000; // in milliseconds private static final int DEFAULT_LINE_BUFFER_TIME = 500; // in milliseconds DirectAudioDevice(DirectAudioDeviceProvider.DirectAudioDeviceInfo portMixerInfo) { // pass in Line.Info, mixer, controls super(portMixerInfo, // Mixer.Info null, // Control[] null, // Line.Info[] sourceLineInfo
*** 166,175 **** --- 166,176 ---- return null; } // ABSTRACT MIXER: ABSTRACT METHOD IMPLEMENTATIONS + @Override public Line getLine(Line.Info info) throws LineUnavailableException { Line.Info fullInfo = getLineInfo(info); if (fullInfo == null) { throw new IllegalArgumentException("Line unsupported: " + info); }
*** 214,224 **** } } throw new IllegalArgumentException("Line unsupported: " + info); } ! public int getMaxLines(Line.Info info) { Line.Info fullInfo = getLineInfo(info); // if it's not supported at all, return 0. if (fullInfo == null) { --- 215,225 ---- } } throw new IllegalArgumentException("Line unsupported: " + info); } ! @Override public int getMaxLines(Line.Info info) { Line.Info fullInfo = getLineInfo(info); // if it's not supported at all, return 0. if (fullInfo == null) {
*** 231,260 **** } return 0; } ! protected void implOpen() throws LineUnavailableException { if (Printer.trace) Printer.trace("DirectAudioDevice: implOpen - void method"); } protected void implClose() { if (Printer.trace) Printer.trace("DirectAudioDevice: implClose - void method"); } protected void implStart() { if (Printer.trace) Printer.trace("DirectAudioDevice: implStart - void method"); } protected void implStop() { if (Printer.trace) Printer.trace("DirectAudioDevice: implStop - void method"); } - - // IMPLEMENTATION HELPERS - int getMixerIndex() { return ((DirectAudioDeviceProvider.DirectAudioDeviceInfo) getMixerInfo()).getIndex(); } int getDeviceID() { --- 232,261 ---- } return 0; } ! @Override protected void implOpen() throws LineUnavailableException { if (Printer.trace) Printer.trace("DirectAudioDevice: implOpen - void method"); } + @Override protected void implClose() { if (Printer.trace) Printer.trace("DirectAudioDevice: implClose - void method"); } + @Override protected void implStart() { if (Printer.trace) Printer.trace("DirectAudioDevice: implStart - void method"); } + @Override protected void implStop() { if (Printer.trace) Printer.trace("DirectAudioDevice: implStop - void method"); } int getMixerIndex() { return ((DirectAudioDeviceProvider.DirectAudioDeviceInfo) getMixerInfo()).getIndex(); } int getDeviceID() {
*** 317,332 **** format.getFrameSize(), format.getFrameRate(), format.isBigEndian()); } return null; } - - - - // INNER CLASSES - - /** * Private inner class for the DataLine.Info objects * adds a little magic for the isFormatSupported so * that the automagic conversion of endianness and sign * does not show up in the formats array. --- 318,327 ----
*** 365,375 **** return hardwareFormats; } } /** ! * Private inner class as base class for direct lines */ private static class DirectDL extends AbstractDataLine implements EventDispatcher.LineMonitor { protected final int mixerIndex; protected final int deviceID; protected long id; --- 360,370 ---- return hardwareFormats; } } /** ! * Private inner class as base class for direct lines. */ private static class DirectDL extends AbstractDataLine implements EventDispatcher.LineMonitor { protected final int mixerIndex; protected final int deviceID; protected long id;
*** 395,405 **** protected volatile boolean noService = false; // do not run the nService method // Guards all native calls. protected final Object lockNative = new Object(); - // CONSTRUCTOR protected DirectDL(DataLine.Info info, DirectAudioDevice mixer, AudioFormat format, int bufferSize, int mixerIndex, --- 390,399 ----
*** 412,426 **** this.waitTime = 10; // 10 milliseconds default wait time this.isSource = isSource; } ! ! // ABSTRACT METHOD IMPLEMENTATIONS ! ! // ABSTRACT LINE / DATALINE ! void implOpen(AudioFormat format, int bufferSize) throws LineUnavailableException { if (Printer.trace) Printer.trace(">> DirectDL: implOpen("+format+", "+bufferSize+" bytes)"); // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions Toolkit.isFullySpecifiedAudioFormat(format); --- 406,416 ---- this.waitTime = 10; // 10 milliseconds default wait time this.isSource = isSource; } ! @Override void implOpen(AudioFormat format, int bufferSize) throws LineUnavailableException { if (Printer.trace) Printer.trace(">> DirectDL: implOpen("+format+", "+bufferSize+" bytes)"); // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions Toolkit.isFullySpecifiedAudioFormat(format);
*** 536,546 **** calcVolume(); if (Printer.trace) Printer.trace("<< DirectDL: implOpen() succeeded"); } ! void implStart() { if (Printer.trace) Printer.trace(" >> DirectDL: implStart()"); // check for record permission if (!isSource) { --- 526,536 ---- calcVolume(); if (Printer.trace) Printer.trace("<< DirectDL: implOpen() succeeded"); } ! @Override void implStart() { if (Printer.trace) Printer.trace(" >> DirectDL: implStart()"); // check for record permission if (!isSource) {
*** 568,577 **** --- 558,568 ---- } if (Printer.trace) Printer.trace("<< DirectDL: implStart() succeeded"); } + @Override void implStop() { if (Printer.trace) Printer.trace(">> DirectDL: implStop()"); // check for record permission if (!isSource) {
*** 598,607 **** --- 589,599 ---- stoppedWritten = false; if (Printer.trace) Printer.trace(" << DirectDL: implStop() succeeded"); } + @Override void implClose() { if (Printer.trace) Printer.trace(">> DirectDL: implClose()"); // check for record permission if (!isSource) {
*** 623,634 **** bytePosition = 0; softwareConversionSize = 0; if (Printer.trace) Printer.trace("<< DirectDL: implClose() succeeded"); } ! // METHOD OVERRIDES ! public int available() { if (id == 0) { return 0; } int a; --- 615,625 ---- bytePosition = 0; softwareConversionSize = 0; if (Printer.trace) Printer.trace("<< DirectDL: implClose() succeeded"); } ! @Override public int available() { if (id == 0) { return 0; } int a;
*** 636,646 **** a = nAvailable(id, isSource); } return a; } ! public void drain() { noService = true; // additional safeguard against draining forever // this occurred on Solaris 8 x86, probably due to a bug // in the audio driver --- 627,637 ---- a = nAvailable(id, isSource); } return a; } ! @Override public void drain() { noService = true; // additional safeguard against draining forever // this occurred on Solaris 8 x86, probably due to a bug // in the audio driver
*** 679,688 **** --- 670,680 ---- drained = true; } noService = false; } + @Override public void flush() { if (id != 0) { // first stop ongoing read/write method flushing = true; synchronized(lock) {
*** 697,706 **** --- 689,699 ---- drained = true; } } // replacement for getFramePosition (see AbstractDataLine) + @Override public long getLongFramePosition() { long pos; synchronized (lockNative) { pos = nGetBytePosition(id, isSource, bytePosition); }
*** 711,721 **** pos = 0; } return (pos / getFormat().getFrameSize()); } - /* * write() belongs into SourceDataLine and Clip, * so define it here and make it accessible by * declaring the respective interfaces with DirectSDL and DirectClip */ --- 704,713 ----
*** 784,793 **** --- 776,786 ---- protected boolean requiresServicing() { return nRequiresServicing(id, isSource); } // called from event dispatcher for lines that need servicing + @Override public void checkLine() { synchronized (lockNative) { if (monitoring && doIO && id != 0
*** 824,834 **** rightGain = gain; } } } - /////////////////// CONTROLS ///////////////////////////// protected final class Gain extends FloatControl { private float linearGain = 1.0f; --- 817,826 ----
*** 842,851 **** --- 834,844 ---- -1, 0.0f, "dB", "Minimum", "", "Maximum"); } + @Override public void setValue(float newValue) { // adjust value within range ?? spec says IllegalArgumentException //newValue = Math.min(newValue, getMaximum()); //newValue = Math.max(newValue, getMinimum());
*** 859,875 **** float getLinearGain() { return linearGain; } } // class Gain - private final class Mute extends BooleanControl { private Mute() { super(BooleanControl.Type.MUTE, false, "True", "False"); } public void setValue(boolean newValue) { super.setValue(newValue); calcVolume(); } } // class Mute --- 852,868 ---- float getLinearGain() { return linearGain; } } // class Gain private final class Mute extends BooleanControl { private Mute() { super(BooleanControl.Type.MUTE, false, "True", "False"); } + @Override public void setValue(boolean newValue) { super.setValue(newValue); calcVolume(); } } // class Mute
*** 879,888 **** --- 872,882 ---- private Balance() { super(FloatControl.Type.BALANCE, -1.0f, 1.0f, (1.0f / 128.0f), -1, 0.0f, "", "Left", "Center", "Right"); } + @Override public void setValue(float newValue) { setValueImpl(newValue); panControl.setValueImpl(newValue); calcVolume(); }
*** 898,929 **** private Pan() { super(FloatControl.Type.PAN, -1.0f, 1.0f, (1.0f / 128.0f), -1, 0.0f, "", "Left", "Center", "Right"); } public void setValue(float newValue) { setValueImpl(newValue); balanceControl.setValueImpl(newValue); calcVolume(); } void setValueImpl(float newValue) { super.setValue(newValue); } } // class Pan - - - } // class DirectDL - /** ! * Private inner class representing a SourceDataLine */ private static final class DirectSDL extends DirectDL implements SourceDataLine { - // CONSTRUCTOR private DirectSDL(DataLine.Info info, AudioFormat format, int bufferSize, DirectAudioDevice mixer) { super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), true); --- 892,919 ---- private Pan() { super(FloatControl.Type.PAN, -1.0f, 1.0f, (1.0f / 128.0f), -1, 0.0f, "", "Left", "Center", "Right"); } + @Override public void setValue(float newValue) { setValueImpl(newValue); balanceControl.setValueImpl(newValue); calcVolume(); } void setValueImpl(float newValue) { super.setValue(newValue); } } // class Pan } // class DirectDL /** ! * Private inner class representing a SourceDataLine. */ private static final class DirectSDL extends DirectDL implements SourceDataLine { private DirectSDL(DataLine.Info info, AudioFormat format, int bufferSize, DirectAudioDevice mixer) { super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), true);
*** 931,956 **** } } /** ! * Private inner class representing a TargetDataLine */ private static final class DirectTDL extends DirectDL implements TargetDataLine { - // CONSTRUCTOR private DirectTDL(DataLine.Info info, AudioFormat format, int bufferSize, DirectAudioDevice mixer) { super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), false); if (Printer.trace) Printer.trace("DirectTDL CONSTRUCTOR: completed"); } ! // METHOD OVERRIDES ! public int read(byte[] b, int off, int len) { flushing = false; if (len == 0) { return 0; } --- 921,944 ---- } } /** ! * Private inner class representing a TargetDataLine. */ private static final class DirectTDL extends DirectDL implements TargetDataLine { private DirectTDL(DataLine.Info info, AudioFormat format, int bufferSize, DirectAudioDevice mixer) { super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), false); if (Printer.trace) Printer.trace("DirectTDL CONSTRUCTOR: completed"); } ! @Override public int read(byte[] b, int off, int len) { flushing = false; if (len == 0) { return 0; }
*** 1028,1048 **** private int loopEndFrame; // the last sample included in the loop // auto closing clip support private boolean autoclosing = false; - // CONSTRUCTOR private DirectClip(DataLine.Info info, AudioFormat format, int bufferSize, DirectAudioDevice mixer) { super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), true); if (Printer.trace) Printer.trace("DirectClip CONSTRUCTOR: completed"); } // CLIP METHODS public void open(AudioFormat format, byte[] data, int offset, int bufferSize) throws LineUnavailableException { // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions Toolkit.isFullySpecifiedAudioFormat(format); --- 1016,1036 ---- private int loopEndFrame; // the last sample included in the loop // auto closing clip support private boolean autoclosing = false; private DirectClip(DataLine.Info info, AudioFormat format, int bufferSize, DirectAudioDevice mixer) { super(info, mixer, format, bufferSize, mixer.getMixerIndex(), mixer.getDeviceID(), true); if (Printer.trace) Printer.trace("DirectClip CONSTRUCTOR: completed"); } // CLIP METHODS + @Override public void open(AudioFormat format, byte[] data, int offset, int bufferSize) throws LineUnavailableException { // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions Toolkit.isFullySpecifiedAudioFormat(format);
*** 1109,1119 **** getEventDispatcher().autoClosingClipOpened(this); } if (Printer.trace) Printer.trace("< DirectClip.open completed"); } ! public void open(AudioInputStream stream) throws LineUnavailableException, IOException { // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions Toolkit.isFullySpecifiedAudioFormat(format); --- 1097,1107 ---- getEventDispatcher().autoClosingClipOpened(this); } if (Printer.trace) Printer.trace("< DirectClip.open completed"); } ! @Override public void open(AudioInputStream stream) throws LineUnavailableException, IOException { // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions Toolkit.isFullySpecifiedAudioFormat(format);
*** 1176,1196 **** if (Printer.trace) Printer.trace("< DirectClip.open(stream) succeeded"); } // synchronized } ! public int getFrameLength() { return m_lengthInFrames; } ! public long getMicrosecondLength() { return Toolkit.frames2micros(getFormat(), getFrameLength()); } ! public void setFramePosition(int frames) { if (Printer.trace) Printer.trace("> DirectClip: setFramePosition: " + frames); if (frames < 0) { frames = 0; --- 1164,1184 ---- if (Printer.trace) Printer.trace("< DirectClip.open(stream) succeeded"); } // synchronized } ! @Override public int getFrameLength() { return m_lengthInFrames; } ! @Override public long getMicrosecondLength() { return Toolkit.frames2micros(getFormat(), getFrameLength()); } ! @Override public void setFramePosition(int frames) { if (Printer.trace) Printer.trace("> DirectClip: setFramePosition: " + frames); if (frames < 0) { frames = 0;
*** 1227,1236 **** --- 1215,1225 ---- +" getLongFramePosition()="+getLongFramePosition()); if (Printer.trace) Printer.trace("< DirectClip: setFramePosition"); } // replacement for getFramePosition (see AbstractDataLine) + @Override public long getLongFramePosition() { /* $$fb * this would be intuitive, but the definition of getFramePosition * is the number of frames rendered since opening the device... * That also means that setFramePosition() means something very
*** 1241,1260 **** //return newFramePosition; //} return super.getLongFramePosition(); } ! public synchronized void setMicrosecondPosition(long microseconds) { if (Printer.trace) Printer.trace("> DirectClip: setMicrosecondPosition: " + microseconds); long frames = Toolkit.micros2frames(getFormat(), microseconds); setFramePosition((int) frames); if (Printer.trace) Printer.trace("< DirectClip: setMicrosecondPosition succeeded"); } public void setLoopPoints(int start, int end) { if (Printer.trace) Printer.trace("> DirectClip: setLoopPoints: start: " + start + " end: " + end); if (start < 0 || start >= getFrameLength()) { throw new IllegalArgumentException("illegal value for start: "+start); --- 1230,1250 ---- //return newFramePosition; //} return super.getLongFramePosition(); } ! @Override public synchronized void setMicrosecondPosition(long microseconds) { if (Printer.trace) Printer.trace("> DirectClip: setMicrosecondPosition: " + microseconds); long frames = Toolkit.micros2frames(getFormat(), microseconds); setFramePosition((int) frames); if (Printer.trace) Printer.trace("< DirectClip: setMicrosecondPosition succeeded"); } + @Override public void setLoopPoints(int start, int end) { if (Printer.trace) Printer.trace("> DirectClip: setLoopPoints: start: " + start + " end: " + end); if (start < 0 || start >= getFrameLength()) { throw new IllegalArgumentException("illegal value for start: "+start);
*** 1281,1311 **** if (Printer.trace) Printer.trace(" loopStart: " + loopStartFrame + " loopEnd: " + loopEndFrame); if (Printer.trace) Printer.trace("< DirectClip: setLoopPoints completed"); } ! public void loop(int count) { // note: when count reaches 0, it means that the entire clip // will be played, i.e. it will play past the loop end point loopCount = count; start(); } ! // ABSTRACT METHOD IMPLEMENTATIONS ! ! // ABSTRACT LINE ! void implOpen(AudioFormat format, int bufferSize) throws LineUnavailableException { // only if audioData wasn't set in a calling open(format, byte[], frameSize) // this call is allowed. if (audioData == null) { throw new IllegalArgumentException("illegal call to open() in interface Clip"); } super.implOpen(format, bufferSize); } void implClose() { if (Printer.trace) Printer.trace(">> DirectClip: implClose()"); // dispose of thread Thread oldThread = thread; --- 1271,1299 ---- if (Printer.trace) Printer.trace(" loopStart: " + loopStartFrame + " loopEnd: " + loopEndFrame); if (Printer.trace) Printer.trace("< DirectClip: setLoopPoints completed"); } ! @Override public void loop(int count) { // note: when count reaches 0, it means that the entire clip // will be played, i.e. it will play past the loop end point loopCount = count; start(); } ! @Override void implOpen(AudioFormat format, int bufferSize) throws LineUnavailableException { // only if audioData wasn't set in a calling open(format, byte[], frameSize) // this call is allowed. if (audioData == null) { throw new IllegalArgumentException("illegal call to open() in interface Clip"); } super.implOpen(format, bufferSize); } + @Override void implClose() { if (Printer.trace) Printer.trace(">> DirectClip: implClose()"); // dispose of thread Thread oldThread = thread;
*** 1331,1347 **** getEventDispatcher().autoClosingClipClosed(this); if (Printer.trace) Printer.trace("<< DirectClip: implClose() succeeded"); } ! void implStart() { if (Printer.trace) Printer.trace("> DirectClip: implStart()"); super.implStart(); if (Printer.trace) Printer.trace("< DirectClip: implStart() succeeded"); } void implStop() { if (Printer.trace) Printer.trace(">> DirectClip: implStop()"); super.implStop(); // reset loopCount field so that playback will be normal with --- 1319,1336 ---- getEventDispatcher().autoClosingClipClosed(this); if (Printer.trace) Printer.trace("<< DirectClip: implClose() succeeded"); } ! @Override void implStart() { if (Printer.trace) Printer.trace("> DirectClip: implStart()"); super.implStart(); if (Printer.trace) Printer.trace("< DirectClip: implStart() succeeded"); } + @Override void implStop() { if (Printer.trace) Printer.trace(">> DirectClip: implStop()"); super.implStop(); // reset loopCount field so that playback will be normal with
*** 1349,1360 **** loopCount = 0; if (Printer.trace) Printer.trace("<< DirectClip: implStop() succeeded"); } - // main playback loop public void run() { if (Printer.trace) Printer.trace(">>> DirectClip: run() threadID="+Thread.currentThread().getId()); while (thread != null) { // doIO is volatile, but we could check it, then get // pre-empted while another thread changes doIO and notifies, --- 1338,1349 ---- loopCount = 0; if (Printer.trace) Printer.trace("<< DirectClip: implStop() succeeded"); } // main playback loop + @Override public void run() { if (Printer.trace) Printer.trace(">>> DirectClip: run() threadID="+Thread.currentThread().getId()); while (thread != null) { // doIO is volatile, but we could check it, then get // pre-empted while another thread changes doIO and notifies,
*** 1416,1429 **** --- 1405,1420 ---- /* $$mp 2003-10-01 The following two methods are common between this class and MixerClip. They should be moved to a base class, together with the instance variable 'autoclosing'. */ + @Override public boolean isAutoClosing() { return autoclosing; } + @Override public void setAutoClosing(boolean value) { if (value != autoclosing) { if (isOpen()) { if (value) { getEventDispatcher().autoClosingClipOpened(this);
*** 1433,1442 **** --- 1424,1434 ---- } autoclosing = value; } } + @Override protected boolean requiresServicing() { // no need for servicing for Clips return false; }
*** 1486,1492 **** // returns if the native implementation needs regular calls to nService() private static native boolean nRequiresServicing(long id, boolean isSource); // called in irregular intervals private static native void nService(long id, boolean isSource); - } --- 1478,1483 ----
< prev index next >