MidiDeviceManager.java
package com.github.dakusui.symfonion.utils.midi;
import com.github.dakusui.symfonion.exceptions.ExceptionThrower;
import com.github.dakusui.valid8j_pcond.forms.Printables;
import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.*;
import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.ContextKey.MIDI_DEVICE_INFO;
import static com.github.dakusui.symfonion.exceptions.ExceptionThrower.ContextKey.MIDI_DEVICE_INFO_IO;
import static com.github.dakusui.symfonion.utils.Utils.onlyElement;
public class MidiDeviceManager {
final List<MidiDeviceRecord> records;
final MidiDeviceReportFormatter reportFormatter;
public MidiDeviceManager(MidiDeviceReportFormatter formatter) {
this.reportFormatter = formatter;
this.records = new LinkedList<>();
}
public MidiDeviceRecord lookUp(Predicate<MidiDeviceRecord> whereClause) {
return this.find(whereClause)
.collect(onlyElement((e1, e2) -> multipleMidiDevices(e1, e2, whereClause)))
.orElseThrow(() -> noSuchMidiDeviceWasFound(whereClause));
}
public static MidiDeviceManager from(MidiDeviceReportFormatter reportFormatter) {
return from(reportFormatter, MidiUtils.streamMidiDeviceInfo());
}
public static MidiDeviceManager from(MidiDeviceReportFormatter reportFormatter, Stream<MidiDevice.Info> midiDeviceInfoStream) {
MidiDeviceManager reportComposer = new MidiDeviceManager(reportFormatter);
midiDeviceInfoStream.forEach(reportComposer::add);
return reportComposer;
}
public static Predicate<MidiDeviceRecord> matchesPortNameInDefinitions(String inPortName, Map<String, Pattern> midiInDefinitions) {
return midiDeviceInfoMatches(midiInDefinitions.get(inPortName));
}
private static Predicate<MidiDeviceRecord> midiDeviceInfoMatches(Pattern regexForDeviceName) {
return printablePredicate(".info.name.matches[" + regexForDeviceName + "]", r -> regexForDeviceName.matcher(r.info().getName()).matches());
}
public static Predicate<MidiDeviceRecord> isMidiDeviceForInput() {
return printablePredicate("isMidiDeviceForInput", r -> MidiUtils.isMidiDeviceForInput(r.info()));
}
public static Predicate<MidiDeviceRecord> isMidiDeviceForOutput() {
return printablePredicate("isMidiDeviceForOutput", r -> MidiUtils.isMidiDeviceForOutput(r.info()));
}
private static <T> Predicate<T> printablePredicate(String name, Predicate<T> p) {
return Printables.predicate(name, p);
}
public static MidiDeviceRecord lookUpMidiDevice(Predicate<MidiDeviceRecord> whereClause, MidiDeviceManager midiDeviceManager) {
return midiDeviceManager.lookUp(whereClause);
}
public MidiDeviceManager add(MidiDevice.Info info) {
return this.add(MidiDeviceRecord.fromMidiDeviceInfo(info));
}
public MidiDeviceManager add(MidiDeviceRecord record) {
this.records.add(record);
return this;
}
public Stream<MidiDeviceRecord> find(Predicate<MidiDeviceRecord> cond) {
return streamRecords().filter(cond);
}
private Stream<MidiDeviceRecord> streamRecords() {
return this.records.stream();
}
public MidiDevice openMidiDevice(MidiDeviceRecord deviceRecord) {
try (ExceptionThrower.Context ignored = context($(MIDI_DEVICE_INFO, deviceRecord.info()), $(MIDI_DEVICE_INFO_IO, deviceRecord.io()))) {
return openMidiDevice(deviceRecord.info());
}
}
public MidiDevice openMidiDevice(MidiDevice.Info info) {
try {
MidiDevice ret = MidiSystem.getMidiDevice(info);
ret.open();
return ret;
} catch (MidiUnavailableException e) {
throw ExceptionThrower.failedToOpenMidiDevice(e);
}
}
public List<String> composeReport(Predicate<MidiDeviceRecord> cond, final MidiDeviceReportFormatter reportFormatter, final String title) {
MidiDevice.Info dummyInfoForHeader = new MidiDevice.Info("name", "vendor", "description", "version") {
};
return new ArrayList<>() {
{
this.addAll(reportFormatter.header(dummyInfoForHeader, title)
.stream()
.map(s -> reportFormatter.formatResult(false, s))
.toList());
this.addAll(MidiDeviceManager.this.records
.stream()
.map(r -> reportFormatter.formatResult(cond.test(r), reportFormatter.formatRecord(r)))
.toList());
this.addAll(reportFormatter.footer().stream().map(s -> reportFormatter.formatResult(false, s)).toList());
}
};
}
}