AudioManager: a bit of cleanup

This commit is contained in:
Neil Gentleman 2016-11-01 20:57:51 -07:00
parent 366e8e281d
commit 843466b6ad
2 changed files with 81 additions and 82 deletions

View file

@ -277,30 +277,30 @@ public class AudioManager {
checkAndPlayClip(getManager().playerWon);
}
private static boolean audioGroupEnabled(AudioGroup audioGroup) {
switch (audioGroup) {
case GameSounds:
return "true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_GAME_ON, "true"));
case DraftSounds:
return "true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_DRAFT_ON, "true"));
case SkipSounds:
return "true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_SKIP_BUTTONS_ON, "true"));
case OtherSounds:
return "true".equals(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_OTHER_ON, "true"));
}
return false;
}
private static void checkAndPlayClip(MageClip mageClip) {
try {
if (mageClip != null) {
boolean playSound = false;
switch (mageClip.getAudioGroup()) {
case GameSounds:
playSound = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_GAME_ON, "true").equals("true");
break;
case DraftSounds:
playSound = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_DRAFT_ON, "true").equals("true");
break;
case SkipSounds:
playSound = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_SKIP_BUTTONS_ON, "true").equals("true");
break;
case OtherSounds:
playSound = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SOUNDS_OTHER_ON, "true").equals("true");
}
if (playSound) {
audioManager.play(mageClip);
}
if (mageClip == null || mageClip.getBuffer() == null) {
return;
}
if (audioGroupEnabled(mageClip.getAudioGroup())) {
audioManager.play(mageClip);
}
} catch (Exception e) {
Logger.getLogger(AudioManager.class).fatal("Error while playing sound clip.", e);
log.warn("Error while playing sound clip.", e);
}
}

View file

@ -1,7 +1,9 @@
package mage.client.util.audio;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
@ -9,9 +11,7 @@ import java.util.TimerTask;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineEvent.Type;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.Mixer;
import javax.sound.sampled.SourceDataLine;
@ -25,11 +25,11 @@ public class LinePool {
private final Logger log = LoggerFactory.getLogger(getClass());
private static final int LINE_CLEANUP_INTERVAL = 30000;
AudioFormat format;
Set<SourceDataLine> freeLines = new HashSet<>();
Set<SourceDataLine> activeLines = new HashSet<>();
Set<SourceDataLine> busyLines = new HashSet<>();
LinkedList<MageClip> queue = new LinkedList<>();
private final Queue<SourceDataLine> freeLines = new ArrayDeque<>();
private final Queue<SourceDataLine> activeLines = new ArrayDeque<>();
private final Set<SourceDataLine> busyLines = new HashSet<>();
private final LinkedList<MageClip> queue = new LinkedList<>();
/*
* Initially all the lines are in the freeLines pool. When a sound plays, one line is being selected randomly from
@ -47,7 +47,6 @@ public class LinePool {
}
public LinePool(AudioFormat audioFormat, int size, int alwaysActive) {
format = audioFormat;
this.alwaysActive = alwaysActive;
mixer = AudioSystem.getMixer(null);
DataLine.Info lineInfo = new DataLine.Info(SourceDataLine.class, audioFormat);
@ -56,11 +55,10 @@ public class LinePool {
SourceDataLine line = (SourceDataLine) mixer.getLine(lineInfo);
freeLines.add(line);
} catch (LineUnavailableException e) {
e.printStackTrace();
log.warn("Failed to get line from mixer", e);
}
}
new Timer("Line cleanup", true).scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
synchronized (LinePool.this) {
@ -75,74 +73,75 @@ public class LinePool {
}, LINE_CLEANUP_INTERVAL, LINE_CLEANUP_INTERVAL);
}
private synchronized SourceDataLine borrowLine() {
SourceDataLine line = activeLines.poll();
if (line == null) {
line = freeLines.poll();
}
if (line != null) {
busyLines.add(line);
}
return line;
}
private synchronized void returnLine(SourceDataLine line) {
busyLines.remove(line);
if (activeLines.size() < alwaysActive) {
activeLines.add(line);
} else {
freeLines.add(line);
}
}
public void playSound(final MageClip mageClip) {
final SourceDataLine line;
synchronized (LinePool.this) {
log.debug("Playing {}", mageClip.getFilename());
logLineStats();
if (activeLines.size() > 0) {
line = activeLines.iterator().next();
} else if (freeLines.size() > 0) {
line = freeLines.iterator().next();
} else {
line = borrowLine();
if (line == null) {
// no lines available, queue sound to play it when a line is available
queue.add(mageClip);
log.debug("Sound {} queued.", mageClip.getFilename());
return;
}
freeLines.remove(line);
activeLines.remove(line);
busyLines.add(line);
logLineStats();
}
ThreadUtils.threadPool.submit(new Runnable() {
@Override
public void run() {
synchronized (LinePool.this) {
try {
if (!line.isOpen()) {
line.open();
line.addLineListener(new LineListener() {
@Override
public void update(LineEvent event) {
log.debug("Event: {}", event);
if (event.getType() != Type.STOP) {
return;
}
synchronized (LinePool.this) {
log.debug("Before stop on line {}", line);
logLineStats();
busyLines.remove(line);
if (activeLines.size() < LinePool.this.alwaysActive) {
activeLines.add(line);
} else {
freeLines.add(line);
}
log.debug("After stop on line {}", line);
logLineStats();
if (queue.size() > 0) {
MageClip queuedSound = queue.poll();
log.debug("Playing queued sound {}", queuedSound);
playSound(queuedSound);
}
}
ThreadUtils.threadPool.submit(() -> {
synchronized (LinePool.this) {
try {
if (!line.isOpen()) {
line.open();
line.addLineListener(event -> {
log.debug("Event: {}", event);
if (event.getType() != Type.STOP) {
return;
}
synchronized (LinePool.this) {
log.debug("Before stop on line {}", line);
logLineStats();
returnLine(line);
log.debug("After stop on line {}", line);
logLineStats();
MageClip queuedSound = queue.poll();
if (queuedSound != null) {
log.debug("Playing queued sound {}", queuedSound);
playSound(queuedSound);
}
});
}
line.start();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
});
}
line.start();
} catch (LineUnavailableException e) {
log.warn("Failed to open line", e);
}
byte[] buffer = mageClip.getBuffer();
log.debug("Before write to line {}", line);
line.write(buffer, 0, buffer.length);
line.drain();
line.stop();
log.debug("Line completed: {}", line);
}
byte[] buffer = mageClip.getBuffer();
log.debug("Before write to line {}", line);
line.write(buffer, 0, buffer.length);
line.drain();
line.stop();
log.debug("Line completed: {}", line);
});
}