mod playing capabilities.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1974 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2002-11-20 04:03:09 +00:00
parent 10523980c6
commit 2178d75392
3 changed files with 137 additions and 36 deletions
@@ -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 + "].");
@@ -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;
}
@@ -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;