Added support for attempting to use an alternate device to play midi,

even thought the java sequencer ignores the new Receiver.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1962 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2002-11-19 02:24:35 +00:00
parent 7f71748537
commit b0aabf1478
@@ -1,5 +1,5 @@
// //
// $Id: SoundManager.java,v 1.17 2002/11/16 03:17:41 ray Exp $ // $Id: SoundManager.java,v 1.18 2002/11/19 02:24:35 ray Exp $
package com.threerings.media; package com.threerings.media;
@@ -20,8 +20,10 @@ import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MetaEventListener; import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage; import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiChannel; import javax.sound.midi.MidiChannel;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem; import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Receiver;
import javax.sound.midi.Sequencer; import javax.sound.midi.Sequencer;
import javax.sound.midi.Synthesizer; import javax.sound.midi.Synthesizer;
@@ -45,6 +47,7 @@ import javax.swing.Timer;
import org.apache.commons.io.StreamUtils; import org.apache.commons.io.StreamUtils;
import com.samskivert.util.CollectionUtil;
import com.samskivert.util.LockableLRUHashMap; import com.samskivert.util.LockableLRUHashMap;
import com.samskivert.util.LRUHashMap; import com.samskivert.util.LRUHashMap;
import com.samskivert.util.Queue; import com.samskivert.util.Queue;
@@ -98,6 +101,8 @@ public class SoundManager
// save things off // save things off
_rmgr = rmgr; _rmgr = rmgr;
initMidi();
// create a thread to plays sounds and load sound // create a thread to plays sounds and load sound
// data from the resource manager // data from the resource manager
_player = new Thread() { _player = new Thread() {
@@ -332,6 +337,78 @@ public class SoundManager
} }
} }
/**
* Get a list of alternate midi devices.
*/
public MidiDevice.Info[] getAlternateMidiDevices ()
{
ArrayList infos = new ArrayList();
CollectionUtil.addAll(infos, MidiSystem.getMidiDeviceInfo());
// remove the synth/seqs, leaving only hardware midi thingies
for (Iterator iter=infos.iterator(); iter.hasNext(); ) {
try {
MidiDevice dev = MidiSystem.getMidiDevice(
(MidiDevice.Info) iter.next());
if ((dev instanceof Sequencer) ||
(dev instanceof Synthesizer)) {
iter.remove();
}
} catch (MidiUnavailableException mue) {
iter.remove();
}
}
return (MidiDevice.Info[]) infos.toArray(
new MidiDevice.Info[infos.size()]);
}
/**
* Attempt to use the alternate midi device for output.
* Return true if we're using it.
*/
public boolean useAlternateDevice (MidiDevice.Info devinfo)
{
Log.info("Trying alternate device: " + devinfo);
try {
MidiDevice dev = MidiSystem.getMidiDevice(devinfo);
Receiver rec = dev.getReceiver();
if (rec == null) {
Log.info("Got no device!");
return false;
}
_stoppingSong = true;
_sequencer.stop();
_sequencer.close();
Receiver old = _sequencer.getTransmitter().getReceiver();
Log.info("Old receiver: " + old);
if (old != null) {
old.close();
}
_sequencer.open();
// THIS DOESN'T WORK.
// See bug #4347135, specifically notes on the bottom.
_sequencer.getTransmitter().setReceiver(rec);
playTopSong();
// possibly shut down an old receiver
if (_receiver != null) {
_receiver.close();
}
// set the new receiver
_receiver = rec;
return true;
} catch (MidiUnavailableException mue) {
Log.warning("Use of alternate device failed [e=" + mue +
", device=" + devinfo + "].");
return false;
}
}
/** /**
* On the SoundManager thread, * On the SoundManager thread,
* plays the sound file with the given pathname. * plays the sound file with the given pathname.
@@ -396,23 +473,6 @@ public class SoundManager
*/ */
protected void playSequence (MidiInfo info) protected void playSequence (MidiInfo info)
{ {
if (_sequencer == null) {
try {
Sequencer seq = MidiSystem.getSequencer();
seq.open();
if (seq instanceof Synthesizer) {
_midiChannels = ((Synthesizer) seq).getChannels();
//updateMusicVolume();
}
_sequencer = seq;
_sequencer.addMetaEventListener(this);
} catch (MidiUnavailableException mue) {
Log.warning("Midi unavailable. Can't play music.");
return;
}
}
stopCurrentSong(false); stopCurrentSong(false);
_midiStack.addFirst(info); _midiStack.addFirst(info);
playTopSong(); playTopSong();
@@ -525,6 +585,27 @@ public class SoundManager
"[path=" + path + "]."); "[path=" + path + "].");
} }
/**
* Initialize the midi system.
*/
protected void initMidi ()
{
try {
Sequencer seq = MidiSystem.getSequencer();
seq.open();
if (seq instanceof Synthesizer) {
_midiChannels = ((Synthesizer) seq).getChannels();
//updateMusicVolume();
}
_sequencer = seq;
_sequencer.addMetaEventListener(this);
} catch (MidiUnavailableException mue) {
Log.warning("Midi unavailable. Can't play music.");
return;
}
}
/** /**
* Stop playing and shutdown the midi system. * Stop playing and shutdown the midi system.
*/ */
@@ -533,6 +614,9 @@ public class SoundManager
_sequencer.removeMetaEventListener(this); _sequencer.removeMetaEventListener(this);
stopCurrentSong(false); stopCurrentSong(false);
_sequencer.close(); _sequencer.close();
if (_receiver != null) {
_receiver.close();
}
_sequencer = null; _sequencer = null;
_midiChannels = null; _midiChannels = null;
_midiStack.clear(); _midiStack.clear();
@@ -932,6 +1016,10 @@ public class SoundManager
/** The sequencer that plays midi music. */ /** The sequencer that plays midi music. */
protected Sequencer _sequencer; protected Sequencer _sequencer;
/** The receiver used to send midi from the sequencer to an alternate
* midi device. */
protected Receiver _receiver;
/** The channels in the sequencer, which we'll use to fuxor volumes. */ /** The channels in the sequencer, which we'll use to fuxor volumes. */
protected MidiChannel[] _midiChannels; protected MidiChannel[] _midiChannels;