Save and load mapped MIDI channels with osci file

pull/38/head
James Ball 2021-12-16 17:11:23 +00:00 zatwierdzone przez James H Ball
rodzic eae07e3e30
commit 2aa73c20d4
1 zmienionych plików z 71 dodań i 21 usunięć

Wyświetl plik

@ -42,7 +42,6 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer; import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
@ -57,14 +56,12 @@ import sh.ball.audio.midi.MidiCommunicator;
import sh.ball.audio.midi.MidiListener; import sh.ball.audio.midi.MidiListener;
import sh.ball.audio.midi.MidiNote; import sh.ball.audio.midi.MidiNote;
import sh.ball.engine.Vector3; import sh.ball.engine.Vector3;
import sh.ball.parser.obj.ObjFrameSettings;
import sh.ball.parser.obj.ObjSettingsFactory; import sh.ball.parser.obj.ObjSettingsFactory;
import sh.ball.parser.obj.ObjParser; import sh.ball.parser.obj.ObjParser;
import sh.ball.parser.ParserFactory; import sh.ball.parser.ParserFactory;
import sh.ball.shapes.Shape; import sh.ball.shapes.Shape;
import sh.ball.shapes.Vector2; import sh.ball.shapes.Vector2;
import static sh.ball.math.Math.round;
import static sh.ball.math.Math.tryParse; import static sh.ball.math.Math.tryParse;
public class Controller implements Initializable, FrequencyListener, MidiListener { public class Controller implements Initializable, FrequencyListener, MidiListener {
@ -711,6 +708,17 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
); );
} }
private void mapMidiCC(int cc, SVGPath midiButton) {
if (CCMap.containsValue(midiButton)) {
CCMap.values().remove(midiButton);
}
if (CCMap.containsKey(cc)) {
CCMap.get(cc).setFill(Color.WHITE);
}
CCMap.put(cc, midiButton);
midiButton.setFill(Color.LIME);
}
// converts MIDI pressure value into a valid value for a slider // converts MIDI pressure value into a valid value for a slider
private double midiPressureToPressure(Slider slider, int midiPressure) { private double midiPressureToPressure(Slider slider, int midiPressure) {
double max = slider.getMax(); double max = slider.getMax();
@ -730,27 +738,20 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
// the audioPlayer handles all non-CC MIDI messages // the audioPlayer handles all non-CC MIDI messages
if (command == ShortMessage.CONTROL_CHANGE) { if (command == ShortMessage.CONTROL_CHANGE) {
int id = message.getData1(); int cc = message.getData1();
int value = message.getData2(); int value = message.getData2();
// if a user has selected a MIDI logo next to a slider, create a mapping // if a user has selected a MIDI logo next to a slider, create a mapping
// between the MIDI channel and the SVG MIDI logo // between the MIDI channel and the SVG MIDI logo
if (armedMidi != null) { if (armedMidi != null) {
if (CCMap.containsValue(armedMidi)) { mapMidiCC(cc, armedMidi);
CCMap.values().remove(armedMidi);
}
if (CCMap.containsKey(id)) {
CCMap.get(id).setFill(Color.WHITE);
}
CCMap.put(id, armedMidi);
armedMidi.setFill(Color.LIME);
armedMidiPaint = null; armedMidiPaint = null;
armedMidi = null; armedMidi = null;
} }
// If there is a slider associated with the MIDI channel, update the value // If there is a slider associated with the MIDI channel, update the value
// of it // of it
if (CCMap.containsKey(id)) { if (CCMap.containsKey(cc)) {
Slider slider = midiButtonMap.get(CCMap.get(id)); Slider slider = midiButtonMap.get(CCMap.get(cc));
double sliderValue = midiPressureToPressure(slider, value); double sliderValue = midiPressureToPressure(slider, value);
if (slider.isSnapToTicks()) { if (slider.isSnapToTicks()) {
@ -786,6 +787,16 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
return List.of("octave", "frequency", "rotateSpeed", "translationSpeed", "volume", return List.of("octave", "frequency", "rotateSpeed", "translationSpeed", "volume",
"visibility", "focalLength", "objectRotateSpeed"); "visibility", "focalLength", "objectRotateSpeed");
} }
private List<Slider> allSliders() {
List<Slider> sliders = new ArrayList<>(checkBoxSliders());
sliders.addAll(otherSliders());
return sliders;
}
private List<String> allLabels() {
List<String> labels = new ArrayList<>(checkBoxLabels());
labels.addAll(otherLabels());
return labels;
}
private void appendSliders(List<Slider> sliders, List<String> labels, Element root, Document document) { private void appendSliders(List<Slider> sliders, List<String> labels, Element root, Document document) {
for (int i = 0; i < sliders.size(); i++) { for (int i = 0; i < sliders.size(); i++) {
@ -813,16 +824,19 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
Element root = document.createElement("project"); Element root = document.createElement("project");
document.appendChild(root); document.appendChild(root);
// Is there a nicer way of doing this?!
List<CheckBox> checkBoxes = checkBoxes(); List<CheckBox> checkBoxes = checkBoxes();
List<Slider> checkBoxSliders = checkBoxSliders(); List<Slider> checkBoxSliders = checkBoxSliders();
List<String> checkBoxLabels = checkBoxLabels(); List<String> checkBoxLabels = checkBoxLabels();
List<Slider> otherSliders = otherSliders(); List<Slider> otherSliders = otherSliders();
List<String> otherLabels = otherLabels(); List<String> otherLabels = otherLabels();
List<Slider> sliders = allSliders();
List<String> labels = allLabels();
Element sliders = document.createElement("sliders"); Element slidersElement = document.createElement("sliders");
appendSliders(checkBoxSliders, checkBoxLabels, sliders, document); appendSliders(checkBoxSliders, checkBoxLabels, slidersElement, document);
appendSliders(otherSliders, otherLabels, sliders, document); appendSliders(otherSliders, otherLabels, slidersElement, document);
root.appendChild(sliders); root.appendChild(slidersElement);
Element checkBoxesElement = document.createElement("checkBoxes"); Element checkBoxesElement = document.createElement("checkBoxes");
for (int i = 0; i < checkBoxes.size(); i++) { for (int i = 0; i < checkBoxes.size(); i++) {
@ -834,6 +848,17 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
} }
root.appendChild(checkBoxesElement); root.appendChild(checkBoxesElement);
Element midiElement = document.createElement("midi");
for (Map.Entry<Integer, SVGPath> entry : CCMap.entrySet()) {
Slider slider = midiButtonMap.get(entry.getValue());
int index = sliders.indexOf(slider);
Integer cc = entry.getKey();
Element midiChannel = document.createElement(labels.get(index));
midiChannel.appendChild(document.createTextNode(cc.toString()));
midiElement.appendChild(midiChannel);
}
root.appendChild(midiElement);
TransformerFactory transformerFactory = TransformerFactory.newInstance(); TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(); Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document); DOMSource domSource = new DOMSource(document);
@ -845,6 +870,13 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
} }
} }
private void resetCCMap() {
armedMidi = null;
armedMidiPaint = null;
CCMap.clear();
midiButtonMap.keySet().forEach(button -> button.setFill(Color.WHITE));
}
private void openProject() { private void openProject() {
try { try {
DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();
@ -859,17 +891,35 @@ public class Controller implements Initializable, FrequencyListener, MidiListene
List<String> checkBoxLabels = checkBoxLabels(); List<String> checkBoxLabels = checkBoxLabels();
List<Slider> otherSliders = otherSliders(); List<Slider> otherSliders = otherSliders();
List<String> otherLabels = otherLabels(); List<String> otherLabels = otherLabels();
List<Slider> sliders = allSliders();
List<String> labels = allLabels();
Element root = doc.getDocumentElement(); Element root = doc.getDocumentElement();
Element sliders = (Element) root.getElementsByTagName("sliders").item(0); Element slidersElement = (Element) root.getElementsByTagName("sliders").item(0);
loadSliderValues(checkBoxSliders, checkBoxLabels, sliders); loadSliderValues(checkBoxSliders, checkBoxLabels, slidersElement);
loadSliderValues(otherSliders, otherLabels, sliders); loadSliderValues(otherSliders, otherLabels, slidersElement);
Element checkBoxesElement = (Element) root.getElementsByTagName("checkBoxes").item(0); Element checkBoxesElement = (Element) root.getElementsByTagName("checkBoxes").item(0);
for (int i = 0; i < checkBoxes.size(); i++) { for (int i = 0; i < checkBoxes.size(); i++) {
String value = checkBoxesElement.getElementsByTagName(checkBoxLabels.get(i)).item(0).getTextContent(); String value = checkBoxesElement.getElementsByTagName(checkBoxLabels.get(i)).item(0).getTextContent();
checkBoxes.get(i).setSelected(Boolean.parseBoolean(value)); checkBoxes.get(i).setSelected(Boolean.parseBoolean(value));
} }
Element midiElement = (Element) root.getElementsByTagName("midi").item(0);
resetCCMap();
for (int i = 0; i < labels.size(); i++) {
NodeList elements = midiElement.getElementsByTagName(labels.get(i));
if (elements.getLength() > 0) {
Element midi = (Element) elements.item(0);
int cc = Integer.parseInt(midi.getTextContent());
Slider slider = sliders.get(i);
SVGPath midiButton = midiButtonMap.entrySet().stream()
.filter(entry -> entry.getValue() == slider)
.findFirst().orElseThrow().getKey();
mapMidiCC(cc, midiButton);
}
}
root.appendChild(midiElement);
} catch (ParserConfigurationException | SAXException | IOException e) { } catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace(); e.printStackTrace();
} }