- 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:
@@ -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;
|
||||
|
||||
@@ -289,6 +289,7 @@ public class SoundManager
|
||||
if (_player != null && (_clipVol != 0f) && isEnabled(type)) {
|
||||
synchronized (_queue) {
|
||||
if (_queue.size() < MAX_QUEUE_SIZE) {
|
||||
Log.debug("play requested [key=" + key + "].");
|
||||
_queue.append(PLAY);
|
||||
_queue.append(new SoundKey(pkgPath, key));
|
||||
|
||||
@@ -348,7 +349,7 @@ public class SoundManager
|
||||
AudioInputStream stream = AudioSystem.getAudioInputStream(
|
||||
new ByteArrayInputStream(data));
|
||||
|
||||
LineSpooler.play(stream, _clipVol);
|
||||
LineSpooler.play(stream, _clipVol, key);
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Error loading sound file [key=" + key +
|
||||
@@ -718,7 +719,8 @@ public class SoundManager
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
AudioFormat format = stream.getFormat();
|
||||
@@ -733,7 +735,7 @@ public class SoundManager
|
||||
_openSpoolers.remove(ii--);
|
||||
nn--;
|
||||
|
||||
} else if (spooler.checkPlay(format, stream, volume)) {
|
||||
} else if (spooler.checkPlay(format, stream, volume, key)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -745,7 +747,7 @@ public class SoundManager
|
||||
|
||||
spooler = new LineSpooler(format);
|
||||
_openSpoolers.add(spooler);
|
||||
spooler.checkPlay(format, stream, volume);
|
||||
spooler.checkPlay(format, stream, volume, key);
|
||||
spooler.start();
|
||||
}
|
||||
|
||||
@@ -801,10 +803,12 @@ public class SoundManager
|
||||
* doing so if we can.
|
||||
*/
|
||||
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)) {
|
||||
_stream = stream;
|
||||
_key = key;
|
||||
SoundManager.adjustVolume(_line, volume);
|
||||
notify();
|
||||
return true;
|
||||
@@ -853,6 +857,7 @@ public class SoundManager
|
||||
int count = 0;
|
||||
byte[] data = new byte[BUFFER_SIZE];
|
||||
|
||||
Log.debug("play happening [key=" + _key.key + "].");
|
||||
while (_valid && count != -1) {
|
||||
try {
|
||||
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
|
||||
// to be a bug in linux's native implementation of drain
|
||||
// that sometimes resulted in the internals of drain
|
||||
// going into an infinite loop. Checking to see if the line
|
||||
// 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
|
||||
// There is a major bug with using drain() under linux. It often
|
||||
// causes the thread to just loop forever inside the native
|
||||
// implementation of drain(), and we're screwed.
|
||||
if (_shouldDrain) {
|
||||
_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.
|
||||
_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. */
|
||||
protected AudioFormat _format;
|
||||
|
||||
@@ -923,15 +906,33 @@ public class SoundManager
|
||||
* we be removed. */
|
||||
protected boolean _valid = true;
|
||||
|
||||
/** Used for debugging. */
|
||||
protected SoundKey _key;
|
||||
|
||||
/** The list of all the currently instantiated spoolers. */
|
||||
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
|
||||
* deciding to shut down. */
|
||||
protected static final long MAX_WAIT_TIME = 30000L;
|
||||
|
||||
/** The maximum number of spoolers we'll allow. This is a lot. */
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user