package openblocks.common;
public class Vario {
private static final int WATCHDOG_PERIOD = 1000 / 20; // nominal game tick
private static final int WATCHDOG_TIMEOUT_TICKS = 10;
private static final int VOL_MIN = 2;
private static final int VOL_MAX = 20;
public static final Vario instance = new Vario();
private int varioVolume = 8;
private boolean isEnabled;
private IVarioController activeController = IVarioController.NULL;
private WatchdogThread watchdogThread;
private final BeepGenerator beeper = new BeepGenerator();
{
setVolume(varioVolume);
}
private class Controller implements IVarioController {
private boolean isValid = true;
@Override
public void setFrequencies(double toneFrequency, double beepFrequency) {
if (isValid) {
beeper.setTargetToneFrequency(toneFrequency);
beeper.setBeepFrequency(beepFrequency);
}
}
@Override
public synchronized void keepAlive() {
if (isValid)
resetWatchdog();
}
@Override
public synchronized void kill() {
if (isValid)
if (watchdogThread != null) watchdogThread.shutdown();
}
@Override
public boolean isValid() {
return isValid;
}
@Override
public void release() {
isValid = false;
}
}
private class WatchdogThread extends Thread {
private boolean isAlive = true;
private int watchdogMissedTicks;
public WatchdogThread() {
setName("Vario watchdog");
setDaemon(true);
}
@Override
public void run() {
try {
while (isAlive && isEnabled) {
if (watchdogMissedTicks++ > WATCHDOG_TIMEOUT_TICKS) {
isAlive = false;
break;
}
if (!beeper.isRunning()) beeper.start();
try {
Thread.sleep(WATCHDOG_PERIOD);
} catch (InterruptedException e) {
isAlive = false;
break;
}
}
} finally {
beeper.stop();
isAlive = false;
}
}
public boolean isShuttingDown() {
return !isAlive || !isEnabled;
}
public void shutdown() {
isAlive = false;
}
public void ping() {
watchdogMissedTicks = 0;
}
}
public void incVolume() {
varioVolume = Math.min((varioVolume + 2), VOL_MAX);
setVolume(varioVolume);
}
public void decVolume() {
varioVolume = Math.max((varioVolume - 2), VOL_MIN);
setVolume(varioVolume);
}
private void setVolume(int volume) {
beeper.setVolume((short)(varioVolume << 8));
}
public void enable() {
isEnabled = true;
}
public void disable() {
isEnabled = false;
}
public boolean isEnabled() {
return isEnabled;
}
public void toggle() {
isEnabled = !isEnabled;
}
public IVarioController acquire() {
if (activeController.isValid())
activeController.release();
return (activeController = new Controller());
}
private void resetWatchdog() {
if (isEnabled) {
if (watchdogThread == null || !watchdogThread.isAlive() || watchdogThread.isShuttingDown()) {
watchdogThread = new WatchdogThread();
watchdogThread.start();
} else if (watchdogThread != null) {
watchdogThread.ping();
}
}
}
}