diff --git a/src/java/com/threerings/media/MP3Manager.java b/src/java/com/threerings/media/MP3Manager.java index 9ff997e5c..fee9c592f 100644 --- a/src/java/com/threerings/media/MP3Manager.java +++ b/src/java/com/threerings/media/MP3Manager.java @@ -1,5 +1,5 @@ // -// $Id: MP3Manager.java,v 1.1 2002/11/20 01:33:34 ray Exp $ +// $Id: MP3Manager.java,v 1.2 2002/11/20 04:03:09 ray Exp $ package com.threerings.media; @@ -37,7 +37,7 @@ public class MP3Manager _player = null; } - public void start (final String path) + public void start (final String set, final String path) { _player = new Thread("narya mp3 relay") { public void run () { @@ -46,7 +46,9 @@ public class MP3Manager inStream = AudioSystem.getAudioInputStream( // new ByteArrayInputStream(StreamUtils.streamAsBytes( // _rmgr.getResource(path), 8192))); - new BufferedInputStream(_rmgr.getResource(path), 4096)); + // TODO: use the fucking resource sets + new BufferedInputStream( + _rmgr.getResource(set, path), 4096)); } catch (Exception e) { Log.warning("MP3 fuckola [path=" + path + ", e=" + e + "]."); diff --git a/src/java/com/threerings/media/sound/ModPlayer.java b/src/java/com/threerings/media/sound/ModPlayer.java new file mode 100644 index 000000000..a1d3cc3cb --- /dev/null +++ b/src/java/com/threerings/media/sound/ModPlayer.java @@ -0,0 +1,89 @@ +// +// $Id: ModPlayer.java,v 1.1 2002/11/20 04:03:09 ray Exp $ + +package com.threerings.media; + +import java.io.DataInputStream; +import java.io.IOException; + +import micromod.MicroMod; +import micromod.Module; +import micromod.ModuleLoader; +import micromod.output.JavaSoundOutputDevice; +import micromod.output.OutputDeviceException; +import micromod.output.PCM16StreamOutputDevice; +import micromod.output.converters.SS16LEAudioFormatConverter; +import micromod.resamplers.LinearResampler; + +import com.threerings.resource.ResourceManager; + +/** + * Does something extraordinary. + */ +public class ModPlayer +{ + public ModPlayer (ResourceManager rmgr, SoundManager smgr) + { + _rmgr = rmgr; + _smgr = smgr; + } + + public void stop () + { + _player = null; + } + + public void start (String set, String path) + { + PCM16StreamOutputDevice devvy = null; + + try { + devvy = new JavaSoundOutputDevice( + new SS16LEAudioFormatConverter(), 44100, 1000); + } catch (OutputDeviceException ode) { + Log.warning("Oh we're fucked with the mod [e=" + ode + "]."); + return; + } + + Module module = null; + try { + module = ModuleLoader.read( + new DataInputStream(_rmgr.getResource(set, path))); + } catch (IOException ioe) { + Log.warning("error loading oh shit oh shit: [e=" + ioe + "]."); + return; + } + + + final PCM16StreamOutputDevice outdev = devvy; + final MicroMod mod = new MicroMod( + module, outdev, new LinearResampler()); + + _player = new Thread("narya mod player") { + public void run () { + + outdev.start(); + while ((_player == Thread.currentThread()) && + (mod.getSequenceLoopCount() == 0)) { + + mod.doRealTimePlayback(); + try { + Thread.sleep(20); + } catch (InterruptedException ie) { + // WFCares + } + } + outdev.stop(); + _smgr.songStopEvent(); + } + }; + + _player.setDaemon(true); + _player.start(); + } + + protected Thread _player; + + protected ResourceManager _rmgr; + protected SoundManager _smgr; +} diff --git a/src/java/com/threerings/media/sound/SoundManager.java b/src/java/com/threerings/media/sound/SoundManager.java index 4485f64c5..2271e071c 100644 --- a/src/java/com/threerings/media/sound/SoundManager.java +++ b/src/java/com/threerings/media/sound/SoundManager.java @@ -1,5 +1,5 @@ // -// $Id: SoundManager.java,v 1.21 2002/11/20 02:41:38 ray Exp $ +// $Id: SoundManager.java,v 1.22 2002/11/20 04:03:09 ray Exp $ package com.threerings.media; @@ -61,6 +61,8 @@ import com.threerings.media.Log; */ // TODO: // - fade music out when stopped? +// -- CLEANUP is NEEDED (lots of references to Sequences, when we're now +// playing mods and mp3s as well. ) public class SoundManager implements MetaEventListener { @@ -107,7 +109,6 @@ public class SoundManager public void run () { Object command = null; SoundKey key = null; - String path = null; MidiInfo midiInfo = null; while (amRunning()) { @@ -119,13 +120,11 @@ public class SoundManager // some commands have an additional argument. if ((PLAY == command) || + (STOPMUSIC == command) || (LOCK == command) || (UNLOCK == command)) { key = (SoundKey) _queue.get(); - } else if (STOPMUSIC == command) { - path = (String) _queue.get(); - } else if (PLAYMUSIC == command) { midiInfo = (MidiInfo) _queue.get(); } @@ -139,7 +138,7 @@ public class SoundManager playSequence(midiInfo); } else if (STOPMUSIC == command) { - stopSequence(path); + stopSequence(key); } else if (LOCK == command) { _clipCache.lock(key); @@ -309,19 +308,19 @@ public class SoundManager /** * Start playing the specified music repeatedly. */ - public void pushMusic (String path) + public void pushMusic (String set, String path) { - pushMusic(path, -1); + pushMusic(set, path, -1); } /** * Start playing music for the specified number of loops. */ - public void pushMusic (String path, int numloops) + public void pushMusic (String set, String path, int numloops) { synchronized (_queue) { _queue.append(PLAYMUSIC); - _queue.append(new MidiInfo(path, numloops)); + _queue.append(new MidiInfo(set, path, numloops)); } } @@ -329,11 +328,11 @@ public class SoundManager * Remove the specified music from the playlist. If it is currently * playing, it will be stopped and the previous song will be started. */ - public void removeMusic (String path) + public void removeMusic (String set, String path) { synchronized (_queue) { _queue.append(STOPMUSIC); - _queue.append(path); + _queue.append(new SoundKey(set, path)); } } @@ -496,9 +495,13 @@ public class SoundManager // start the new one try { if (info.path.endsWith(".mp3")) { - _mp3player.start(info.path); + _mp3player.start(info.set, info.path); + + } else if (info.path.endsWith(".mod")) { + _modplayer.start(info.set, info.path); + } else { - _sequencer.setSequence(getMidiData(info.path)); + _sequencer.setSequence(getMidiData(info)); if (info.msPosition != -1) { // TODO: this doesn't work correctly _sequencer.setTickPosition(info.tickPosition); @@ -538,6 +541,10 @@ public class SoundManager _stoppingSong = true; if (current.path.endsWith(".mp3")) { _mp3player.stop(); + + } else if (current.path.endsWith(".mod")) { + _modplayer.stop(); + } else { _sequencer.stop(); } @@ -566,18 +573,22 @@ public class SoundManager /** * Stop the sequence at the specified path. */ - protected void stopSequence (String path) + protected void stopSequence (SoundKey key) { if (! _midiStack.isEmpty()) { MidiInfo current = (MidiInfo) _midiStack.getFirst(); // if we're currently playing this song.. - if (path.equals(current.path)) { + if (key.equals(current)) { // stop it _stoppingSong = true; - if (path.endsWith(".mp3")) { + if (key.path.endsWith(".mp3")) { _mp3player.stop(); + + } else if (key.path.endsWith(".mod")) { + _modplayer.stop(); + } else { _sequencer.stop(); } @@ -590,7 +601,7 @@ public class SoundManager } else { // we aren't currently playing this song. Simply remove. for (Iterator iter=_midiStack.iterator(); iter.hasNext(); ) { - if (path.equals(((MidiInfo) iter.next()).path)) { + if (key.equals(iter.next())) { iter.remove(); return; } @@ -600,7 +611,7 @@ public class SoundManager } Log.debug("Sequence stopped that wasn't in the stack anymore " + - "[path=" + path + "]."); + "[key=" + key + "]."); } /** @@ -609,6 +620,7 @@ public class SoundManager protected void initMidi () { _mp3player = new MP3Manager(_rmgr, this); + _modplayer = new ModPlayer(_rmgr, this); try { Sequencer seq = MidiSystem.getSequencer(); @@ -747,7 +759,7 @@ public class SoundManager } else { // set it up and put it in the cache AudioInputStream stream = AudioSystem.getAudioInputStream( - getResource(key.set, key.path)); + getResource(key)); DataLine.Info dinfo = new DataLine.Info( Clip.class, stream.getFormat()); info = new ClipInfo(dinfo, stream); @@ -760,18 +772,17 @@ public class SoundManager /** * Get the midi data for the specified path. */ - protected InputStream getMidiData (String path) + protected InputStream getMidiData (MidiInfo info) throws IOException { - InputStream stream = (InputStream) _midiCache.get(path); + InputStream stream = (InputStream) _midiCache.get(info); if (stream != null) { // reset the stream for the new user stream.reset(); } else { - // TODO: unhack - stream = getResource("boot", path); - _midiCache.put(path, stream); + stream = getResource(info); + _midiCache.put(info, stream); } return stream; @@ -782,11 +793,11 @@ public class SoundManager * Get the data specified by the path from the resource bundle. * No caching is done. */ - protected InputStream getResource (String set, String path) + protected InputStream getResource (SoundKey key) throws IOException { return new ByteArrayInputStream(StreamUtils.streamAsBytes( - _rmgr.getResource(set, path), BUFFER_SIZE)); + _rmgr.getResource(key.set, key.path), BUFFER_SIZE)); } /** @@ -1053,11 +1064,8 @@ public class SoundManager /** * A class that tracks the information about our playing midi files. */ - protected static class MidiInfo + protected static class MidiInfo extends SoundKey { - /** The path, duh. */ - public String path; - /** How many times to loop, or -1 for forever. */ public int loops; @@ -1065,9 +1073,9 @@ public class SoundManager public long tickPosition = -1; public long msPosition = -1; - public MidiInfo (String path, int loops) + public MidiInfo (String set, String path, int loops) { - this.path = path; + super(set, path); this.loops = loops; } } @@ -1115,6 +1123,8 @@ public class SoundManager protected MP3Manager _mp3player; + protected ModPlayer _modplayer; + /** The receiver used to send midi from the sequencer to an alternate * midi device. */ protected Receiver _receiver;