Added configurable midi output device selection; will still default to the Java Sound Synth if no selection has been made.

This commit is contained in:
badvision 2017-02-19 22:12:37 -06:00
parent 8a0e633a63
commit b57d3e06e0
2 changed files with 50 additions and 22 deletions

View File

@ -50,8 +50,8 @@ import javax.sound.sampled.SourceDataLine;
*/ */
public class SoundMixer extends Device { public class SoundMixer extends Device {
private final Set<SourceDataLine> availableLines = Collections.synchronizedSet(new HashSet<SourceDataLine>()); private final Set<SourceDataLine> availableLines = Collections.synchronizedSet(new HashSet<>());
private final Map<Object, SourceDataLine> activeLines = Collections.synchronizedMap(new HashMap<Object, SourceDataLine>()); private final Map<Object, SourceDataLine> activeLines = Collections.synchronizedMap(new HashMap<>());
/** /**
* Bits per sample * Bits per sample
*/ */

View File

@ -18,17 +18,21 @@
*/ */
package jace.hardware; package jace.hardware;
import jace.config.ConfigurableField;
import jace.config.DynamicSelection;
import jace.config.Name; import jace.config.Name;
import jace.core.Card; import jace.core.Card;
import jace.core.Computer; import jace.core.Computer;
import jace.core.RAMEvent; import jace.core.RAMEvent;
import jace.core.RAMEvent.TYPE; import jace.core.RAMEvent.TYPE;
import java.util.LinkedHashMap;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MidiDevice; 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.ShortMessage; import javax.sound.midi.ShortMessage;
import javax.sound.midi.Synthesizer; import javax.sound.midi.Synthesizer;
@ -43,6 +47,8 @@ import javax.sound.midi.Synthesizer;
@Name(value = "Passport Midi Interface", description = "MIDI sound card") @Name(value = "Passport Midi Interface", description = "MIDI sound card")
public class PassportMidiInterface extends Card { public class PassportMidiInterface extends Card {
private Receiver midiOut;
public PassportMidiInterface(Computer computer) { public PassportMidiInterface(Computer computer) {
super(computer); super(computer);
} }
@ -57,6 +63,31 @@ public class PassportMidiInterface extends Card {
CONTINUOUS, SINGLE_SHOT, FREQ_COMPARISON, PULSE_COMPARISON CONTINUOUS, SINGLE_SHOT, FREQ_COMPARISON, PULSE_COMPARISON
}; };
@ConfigurableField(name = "Midi Output Device", description = "Midi output device")
public static DynamicSelection<String> preferredMidiDevice = new DynamicSelection<String>(null) {
@Override
public boolean allowNull() {
return false;
}
@Override
public LinkedHashMap<? extends String, String> getSelections() {
LinkedHashMap<String, String> out = new LinkedHashMap<>();
MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
for (MidiDevice.Info dev : devices) {
try {
MidiDevice device = MidiSystem.getMidiDevice(dev);
if (device.getMaxReceivers() > 0 || dev instanceof Synthesizer)
System.out.println("MIDI Device found: " + dev);
out.put(dev.getName(), dev.getName());
} catch (MidiUnavailableException ex) {
Logger.getLogger(PassportMidiInterface.class.getName()).log(Level.SEVERE, null, ex);
}
}
return out;
}
};
public static class PTMTimer { public static class PTMTimer {
// Configuration values // Configuration values
@ -168,8 +199,6 @@ public class PassportMidiInterface extends Card {
private final boolean receiverACIAOverrun = false; private final boolean receiverACIAOverrun = false;
// True if ACIA generated interrupt request // True if ACIA generated interrupt request
private final boolean irqRequestedACIA = false; private final boolean irqRequestedACIA = false;
//--- the synth
private Synthesizer synth;
@Override @Override
public void reset() { public void reset() {
@ -476,13 +505,13 @@ public class PassportMidiInterface extends Card {
// If we have a command to send, then do it // If we have a command to send, then do it
if (sendMessage == true) { if (sendMessage == true) {
if (synth != null && synth.isOpen()) { if (midiOut != null) {
// Send message // Send message
try { try {
// System.out.println("Sending MIDI message "+currentMessageStatus+","+currentMessageData1+","+currentMessageData2); // System.out.println("Sending MIDI message "+currentMessageStatus+","+currentMessageData1+","+currentMessageData2);
currentMessage.setMessage(currentMessageStatus, currentMessageData1, currentMessageData2); currentMessage.setMessage(currentMessageStatus, currentMessageData1, currentMessageData2);
synth.getReceiver().send(currentMessage, -1L); midiOut.send(currentMessage, -1L);
} catch (InvalidMidiDataException | MidiUnavailableException ex) { } catch (InvalidMidiDataException ex) {
Logger.getLogger(PassportMidiInterface.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(PassportMidiInterface.class.getName()).log(Level.SEVERE, null, ex);
} }
} }
@ -509,30 +538,29 @@ public class PassportMidiInterface extends Card {
@Override @Override
public void resume() { public void resume() {
if (isRunning() && synth != null && synth.isOpen()) { if (isRunning() && midiOut != null) {
return; return;
} }
try { try {
MidiDevice selectedDevice = MidiSystem.getSynthesizer();
MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo(); MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
if (devices.length == 0) { if (devices.length == 0) {
System.out.println("No MIDI devices found"); System.out.println("No MIDI devices found");
} else { } else {
for (MidiDevice.Info dev : devices) { for (MidiDevice.Info dev : devices) {
System.out.println("MIDI Device found: " + dev); System.out.println("MIDI Device found: " + dev);
if (dev.getName().contains("Java Sound")) { if ((preferredMidiDevice.getValue() == null && dev.getName().contains("Java Sound") && dev instanceof Synthesizer) ||
if (dev instanceof Synthesizer) { preferredMidiDevice.getValue().equalsIgnoreCase(dev.getName())
synth = (Synthesizer) dev; ) {
break; selectedDevice = MidiSystem.getMidiDevice(dev);
} break;
} }
} }
} }
if (synth == null) { if (selectedDevice != null) {
synth = MidiSystem.getSynthesizer(); System.out.println("Selected MIDI device: " + selectedDevice.getDeviceInfo().getName());
} selectedDevice.open();
if (synth != null) { midiOut = selectedDevice.getReceiver();
System.out.println("Selected MIDI device: " + synth.getDeviceInfo().getName());
synth.open();
super.resume(); super.resume();
} }
} catch (MidiUnavailableException ex) { } catch (MidiUnavailableException ex) {
@ -543,9 +571,9 @@ public class PassportMidiInterface extends Card {
private void suspendACIA() { private void suspendACIA() {
// TODO: Stop ACIA thread... // TODO: Stop ACIA thread...
if (synth != null && synth.isOpen()) { if (midiOut != null) {
synth.close(); midiOut.close();
synth = null; midiOut = null;
} }
} }
} }