- added debug logging so that we can see the time elapsed between the

moment that a sound is requested to just before the LineSpooler object
  that it was given to starts writing the data to a line.
- Turned drain() back on, but only if we're not running under linux.
  If we're in linux, we instead sleep for 3 seconds, and gosh darn it, the
  sound should be finished after that.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2019 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2002-12-04 02:14:12 +00:00
parent 1d9de38b61
commit c321f7eb33
@@ -1,5 +1,5 @@
// //
// $Id: SoundManager.java,v 1.35 2002/11/29 21:22:46 ray Exp $ // $Id: SoundManager.java,v 1.36 2002/12/04 02:14:12 ray Exp $
package com.threerings.media; package com.threerings.media;
@@ -289,6 +289,7 @@ public class SoundManager
if (_player != null && (_clipVol != 0f) && isEnabled(type)) { if (_player != null && (_clipVol != 0f) && isEnabled(type)) {
synchronized (_queue) { synchronized (_queue) {
if (_queue.size() < MAX_QUEUE_SIZE) { if (_queue.size() < MAX_QUEUE_SIZE) {
Log.debug("play requested [key=" + key + "].");
_queue.append(PLAY); _queue.append(PLAY);
_queue.append(new SoundKey(pkgPath, key)); _queue.append(new SoundKey(pkgPath, key));
@@ -348,7 +349,7 @@ public class SoundManager
AudioInputStream stream = AudioSystem.getAudioInputStream( AudioInputStream stream = AudioSystem.getAudioInputStream(
new ByteArrayInputStream(data)); new ByteArrayInputStream(data));
LineSpooler.play(stream, _clipVol); LineSpooler.play(stream, _clipVol, key);
} catch (IOException ioe) { } catch (IOException ioe) {
Log.warning("Error loading sound file [key=" + key + Log.warning("Error loading sound file [key=" + key +
@@ -718,7 +719,8 @@ public class SoundManager
/** /**
* Attempt to play the specified sound. * Attempt to play the specified sound.
*/ */
public static void play (AudioInputStream stream, float volume) public static void play (
AudioInputStream stream, float volume, SoundKey key)
throws LineUnavailableException throws LineUnavailableException
{ {
AudioFormat format = stream.getFormat(); AudioFormat format = stream.getFormat();
@@ -733,7 +735,7 @@ public class SoundManager
_openSpoolers.remove(ii--); _openSpoolers.remove(ii--);
nn--; nn--;
} else if (spooler.checkPlay(format, stream, volume)) { } else if (spooler.checkPlay(format, stream, volume, key)) {
return; return;
} }
} }
@@ -745,7 +747,7 @@ public class SoundManager
spooler = new LineSpooler(format); spooler = new LineSpooler(format);
_openSpoolers.add(spooler); _openSpoolers.add(spooler);
spooler.checkPlay(format, stream, volume); spooler.checkPlay(format, stream, volume, key);
spooler.start(); spooler.start();
} }
@@ -801,10 +803,12 @@ public class SoundManager
* doing so if we can. * doing so if we can.
*/ */
protected synchronized boolean checkPlay ( protected synchronized boolean checkPlay (
AudioFormat format, AudioInputStream stream, float volume) AudioFormat format, AudioInputStream stream, float volume,
SoundKey key)
{ {
if (_valid && (_stream == null) && _format.matches(format)) { if (_valid && (_stream == null) && _format.matches(format)) {
_stream = stream; _stream = stream;
_key = key;
SoundManager.adjustVolume(_line, volume); SoundManager.adjustVolume(_line, volume);
notify(); notify();
return true; return true;
@@ -853,6 +857,7 @@ public class SoundManager
int count = 0; int count = 0;
byte[] data = new byte[BUFFER_SIZE]; byte[] data = new byte[BUFFER_SIZE];
Log.debug("play happening [key=" + _key.key + "].");
while (_valid && count != -1) { while (_valid && count != -1) {
try { try {
count = _stream.read(data, 0, data.length); count = _stream.read(data, 0, data.length);
@@ -869,47 +874,25 @@ public class SoundManager
} }
} }
// SO, I used to just always drain, but I found what appears // There is a major bug with using drain() under linux. It often
// to be a bug in linux's native implementation of drain // causes the thread to just loop forever inside the native
// that sometimes resulted in the internals of drain // implementation of drain(), and we're screwed.
// going into an infinite loop. Checking to see if the line if (_shouldDrain) {
// isActive (engaging in I/O) before calling drain seems
// to have stopped the problem from happening.
//
// TODO: look at this some more.
// For now I'm turning draining back on, because I've seen
// instances of longer sounds reporting that they're not active
// while they're still playing, and so the next sound
// is significantly delayed. That sucks.
//
// Nov 29: drain() definitely hoses things.
// Mike just had 14 threads stuck in drain(). Back off.
if (_line.isActive()) {
// Log.info("Waiting for drain (" + hashCode() + ", active=" +
// _line.isActive() + ", running=" + _line.isRunning()+
// ") : " + incDrainers());
// wait for it to play all the way
_line.drain(); _line.drain();
// Log.info("drained: (" + hashCode() + ") :" + decDrainers()); } else {
// we instead attempt to sleep long enough such that
// everything should be drained.
try {
Thread.sleep(NO_DRAIN_SLEEP_TIME);
} catch (InterruptedException ie) {
}
} }
// clear it out so that we can wait for more. // clear it out so that we can wait for more.
_stream = null; _stream = null;
} }
// protected static final synchronized int incDrainers ()
// {
// return ++drainers;
// }
//
// protected static final synchronized int decDrainers ()
// {
// return --drainers;
// }
// static int drainers = 0;
/** The format that our line was opened with. */ /** The format that our line was opened with. */
protected AudioFormat _format; protected AudioFormat _format;
@@ -923,15 +906,33 @@ public class SoundManager
* we be removed. */ * we be removed. */
protected boolean _valid = true; protected boolean _valid = true;
/** Used for debugging. */
protected SoundKey _key;
/** The list of all the currently instantiated spoolers. */ /** The list of all the currently instantiated spoolers. */
protected static ArrayList _openSpoolers = new ArrayList(); protected static ArrayList _openSpoolers = new ArrayList();
/** Should we attempt to use line.drain()? */
protected static boolean _shouldDrain = true;
/** The maximum time a spooler will wait for a stream before /** The maximum time a spooler will wait for a stream before
* deciding to shut down. */ * deciding to shut down. */
protected static final long MAX_WAIT_TIME = 30000L; protected static final long MAX_WAIT_TIME = 30000L;
/** The maximum number of spoolers we'll allow. This is a lot. */ /** The maximum number of spoolers we'll allow. This is a lot. */
protected static final int MAX_SPOOLERS = 24; protected static final int MAX_SPOOLERS = 24;
/** The time we sleep if it's not safe to drain. */
protected static final long NO_DRAIN_SLEEP_TIME = 3000L;
// see if we should use drain.
static {
String os = System.getProperty("os.name");
if (os == null || (os.indexOf("Linux") != -1)) {
_shouldDrain = false;
Log.info("Detected Linux, will not use drain() on lines.");
}
}
} }
/** /**