package NET.worlds.scape; import NET.worlds.console.Main; import NET.worlds.console.MainCallback; import NET.worlds.console.MainTerminalCallback; import NET.worlds.core.IniFile; import NET.worlds.network.URL; import java.io.File; import java.io.IOException; import java.util.Vector; public class CDAudio implements Runnable, MainCallback, MainTerminalCallback { private static final int STOP = 0; private static final int PLAY = 1; private static final int PAUSE = 2; private static final int NEXT = 3; private static final int PREV = 4; private static final int CHANGE = 5; private static final int CHANGE_MIDI = 6; private boolean performedStartupPlay; private boolean cancel; private Thread playerThread; private Vector commandBuffer = new Vector(); private boolean paused; private int driveID; private CDTrackInfo tracks; private int trackOffset; private Object tracksMutex = new Object(); private int pos; private SoundPlayer midiPlayer; private URL defaultMIDIFile = URL.make("home:start.mid"); private URL curMIDIFile = this.defaultMIDIFile; private int trackToRepeat = -1; private int repeatingTrack = -1; private boolean enabled = true; private static CDAudio instance = new CDAudio(); static boolean useMidiFlag = IniFile.gamma().getIniInt("MIDIONSTART", 1) != 0; static boolean useAutoCDFlag = IniFile.gamma().getIniInt("AUTOPLAYCD", 1) != 0; private boolean cdInDrive; private boolean allowMIDIAnyway; private boolean midiPaused; private boolean midiStarted; public static CDAudio get() { return instance; } public String getTimeReadout() { synchronized (this.tracksMutex) { if (this.tracks == null) { this.tracksMutex.notify(); return "00 [00:00]"; } else { int count = this.tracks.getNumTracks(); if (this.pos != 0) { for (int i = 0; i < count; i++) { if (this.pos < this.tracks.getEndFrames(i)) { return fmt2(i + 1) + " " + fmtFrames(this.pos - this.tracks.getStartFrames(i)); } } } return fmt2(count) + " " + fmtFrames(this.tracks.getEndFrames(count - 1)); } } } public void setEnabled(boolean state) { if (this.enabled != state) { this.enabled = state; if (!this.enabled) { this.stop(); } else { this.change(true); } } } public void play() { this.queueCommand(1); } public void pause() { this.queueCommand(2); } public void stop() { this.queueCommand(0); } public void next() { this.queueCommand(3); } public void prev() { this.queueCommand(4); } public void change(boolean loop) { this.queueCommand(5); } public static void startupPlay() { get(); } public void setMIDIFile(URL url) { this.curMIDIFile = url; } public URL getDefaultMIDIFile() { return this.defaultMIDIFile; } public URL getMIDIFile() { return this.curMIDIFile; } public void setCDTrack(int track) { this.trackToRepeat = track - 1; } public int getCDTrack() { return this.trackToRepeat + 1; } private CDAudio() { this.playerThread = new Thread(this); this.playerThread.start(); } @Override public void run() { Main.register(this); int numDrives = CDPlayerAction.getNumDrives(); while (!this.cancel) { for (int i = 0; i < numDrives; i++) { this.cdInDrive = false; try { if ((this.driveID = CDPlayerAction.openDrive(i)) != 0) { if (!CDPlayerAction.isPlaying(this.driveID)) { CDTrackInfo tmp = CDPlayerAction.getDriveTrackList(this.driveID); char drive = (char)(65 + CDPlayerAction.getDriveLetterOffset(i)); File f = new File(drive + ":\\WORLDS.CD"); if (f.exists()) { synchronized (this.tracksMutex) { this.tracks = tmp; this.trackOffset = 0; if (f.length() == 1L) { this.trackOffset = 1; } } this.cdInDrive = true; if (this.performedStartupPlay) { this.flushPendingCommands(); } else { this.performedStartupPlay = true; } this.change(true); this.waitForCommands(); } } this.driveID = 0; } } catch (IOException var12) { } if (this.driveID != 0) { try { CDPlayerAction.closeDrive(this.driveID); } catch (IOException var10) { } this.driveID = 0; this.paused = false; this.pos = 0; } } this.performedStartupPlay = true; this.cdInDrive = false; synchronized (this.tracksMutex) { this.tracks = null; } if (!this.cancel) { this.timedWait(10); synchronized (this.tracksMutex) { if (!this.cancel) { try { this.tracksMutex.wait(); } catch (InterruptedException var7) { } } } } } Main.unregister(this); } public void useAutoCD(boolean f) { if (f != useAutoCDFlag) { useAutoCDFlag = f; IniFile.gamma().setIniInt("AUTOPLAYCD", useAutoCDFlag ? 1 : 0); if (f) { if (this.trackToRepeat != -1) { this.queueCommand(5); } } else { this.queueCommand(0); } } } private synchronized void flushPendingCommands() { this.commandBuffer.removeAllElements(); } private synchronized void prequeueCommand(int command) { this.commandBuffer.insertElementAt(new Integer(command), 0); } private synchronized void queueCommand(int command) { if (command != 6) { this.allowMIDIAnyway = false; } this.commandBuffer.addElement(new Integer(command)); } private synchronized int getQueuedCommand(boolean isMidi) { if (this.commandBuffer.size() <= 0) { return -1; } else { int command = (Integer)this.commandBuffer.elementAt(0); if (command == 6) { if (!isMidi) { return -1; } } else if (isMidi == this.cdInDrive) { return -1; } this.commandBuffer.removeElementAt(0); return command; } } private synchronized int peekQueuedCommand() { return this.commandBuffer.size() <= 0 ? -1 : (Integer)this.commandBuffer.elementAt(0); } private void waitForCommands() throws IOException { while (!this.cancel) { boolean playing = CDPlayerAction.isPlaying(this.driveID); if (playing) { int tmp = CDPlayerAction.getPosition(this.driveID); if (tmp > this.pos) { this.pos = tmp; } this.paused = false; } else { CDPlayerAction.checkDrive(this.driveID); if (!this.paused) { this.pos = 0; } if (this.repeatingTrack != -1) { this.pos = this.tracks.getStartFrames(this.repeatingTrack + this.trackOffset); CDPlayerAction.playAudio(this.driveID, this.pos, this.tracks.getEndFrames(this.repeatingTrack + this.trackOffset)); } } int command; if ((command = this.getQueuedCommand(false)) >= 0) { this.processCommand(command, playing); } else { this.timedWait(1); } } CDPlayerAction.stopAudio(this.driveID); } private void processCommand(int command, boolean playing) throws IOException { int wasRepeatingTrack = this.repeatingTrack; this.repeatingTrack = -1; switch (command) { case 0: if (playing || this.paused) { CDPlayerAction.stopAudio(this.driveID); } this.paused = false; break; case 1: if (!playing) { this.play(-this.pos); } break; case 2: if (playing && !this.paused) { CDPlayerAction.stopAudio(this.driveID); this.paused = true; } break; case 3: if (!playing && !this.paused) { this.play(0); } else { for (int ix = 0; ix < this.tracks.getNumTracks() - 1; ix++) { if (this.pos >= this.tracks.getStartFrames(ix) && this.pos < this.tracks.getEndFrames(ix)) { this.play(ix + 1); return; } } } break; case 4: if (playing || this.paused) { for (int i = 0; i < this.tracks.getNumTracks(); i++) { if (this.pos < this.tracks.getEndFrames(i)) { if (i > 0 && this.pos < this.tracks.getStartFrames(i) + 75) { this.play(i - 1); } else { this.play(i); } break; } } } break; case 5: if (useAutoCDFlag && this.enabled) { if (this.trackToRepeat == -1 || this.trackToRepeat < this.tracks.getNumTracks()) { this.repeatingTrack = this.trackToRepeat; if (wasRepeatingTrack == this.trackToRepeat && wasRepeatingTrack != -1) { return; } } CDPlayerAction.stopAudio(this.driveID); if (this.repeatingTrack == -1) { this.allowMIDIAnyway = true; this.queueCommand(6); } this.paused = false; } } } private void play(int location) throws IOException { if (location < 0) { this.pos = -location; } else { this.pos = this.tracks.getStartFrames(location); } CDPlayerAction.playAudio(this.driveID, this.pos, this.tracks.getEndFrames(this.tracks.getNumTracks() - 1)); this.paused = false; } private void startMidi() { if (this.curMIDIFile != this.defaultMIDIFile) { if (this.midiPlayer != null) { this.midiPlayer.stop(); this.midiPlayer.close(); this.midiStarted = false; if (MCISoundPlayer.isActive() || WMPSoundPlayer.isActive()) { this.midiPlayer = null; return; } } else if (MCISoundPlayer.isActive() || WMPSoundPlayer.isActive()) { return; } Sound s = new Sound(this.curMIDIFile); if (!this.curMIDIFile.endsWith(".mid") && !this.curMIDIFile.endsWith(".wav")) { this.midiPlayer = new WMPSoundPlayer(s); } else { this.midiPlayer = new MCISoundPlayer(s); } this.midiPlayer.open(1.0F, 0.0F, false, false); if (!this.midiPaused) { this.midiPlayer.start(1); } } } private void killMidi() { if (this.midiPlayer != null) { this.midiStarted = false; this.midiPlayer.stop(); this.midiPlayer.close(); this.midiPlayer = null; } } private void useMidi() { if (useMidiFlag && this.enabled && (!this.cdInDrive || this.allowMIDIAnyway)) { if (this.midiPlayer == null) { this.startMidi(); } else if (this.midiPlayer.getState() == 1) { if (this.midiStarted) { this.startMidi(); this.midiStarted = false; } } else { this.midiStarted = true; } } if (!useMidiFlag || !this.enabled || this.cdInDrive && !this.allowMIDIAnyway) { this.killMidi(); } } public void setMidiFlag(boolean f) { useMidiFlag = f; IniFile.gamma().setIniInt("MIDIONSTART", useMidiFlag ? 1 : 0); } @Override public void mainCallback() { if (this.performedStartupPlay) { this.useMidi(); while (this.midiPlayer != null || this.peekQueuedCommand() == 6) { if (this.cdInDrive && this.repeatingTrack != -1) { if (this.peekQueuedCommand() == 6) { this.getQueuedCommand(true); } this.allowMIDIAnyway = false; this.useMidi(); return; } int command; if ((command = this.getQueuedCommand(true)) < 0) { return; } switch (command) { case 0: case 2: this.midiPaused = true; this.midiPlayer.stop(); this.midiStarted = false; break; case 1: if (this.midiPaused || !this.midiStarted) { this.midiPaused = false; this.startMidi(); } break; case 3: case 4: this.startMidi(); break; case 5: case 6: if (useMidiFlag && this.enabled) { this.midiStarted = false; this.midiPaused = false; this.startMidi(); } } } } } private synchronized void timedWait(int secs) { if (!this.cancel) { try { this.wait(secs * 1000); } catch (InterruptedException var3) { } } } @Override public void terminalCallback() { this.cancel = true; this.killMidi(); synchronized (this) { this.notify(); } synchronized (this.tracksMutex) { this.tracksMutex.notify(); } } private static String fmt2(int val) { return val < 10 ? "0" + val : "" + val; } private static String fmtFrames(int frames) { if (frames < 0) { frames = 0; } int minutes = frames / 4500; frames -= minutes * 4500; int seconds = frames / 75; return "[" + fmt2(minutes) + ":" + fmt2(seconds) + "]"; } }