X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=_MIDI.pde;h=b0b8fc4ca9bd46e650c168881601edbf5478162e;hb=6b163a98976a5f2adf9da1b7bd3297e39d6dd7bf;hp=323efeeec641c8ad7412d89d68b1d19b0ec543e9;hpb=ff23d1911e58a2fdebb3da6f6073a6fd64c4eef4;p=SugarCubes.git diff --git a/_MIDI.pde b/_MIDI.pde index 323efee..b0b8fc4 100644 --- a/_MIDI.pde +++ b/_MIDI.pde @@ -22,6 +22,7 @@ interface MidiEngineListener { class MidiEngine { + public final GridController grid; private final List listeners = new ArrayList(); private final List midiControllers = new ArrayList(); @@ -41,17 +42,17 @@ class MidiEngine { private int activeDeckIndex = 0; public MidiEngine() { - - midiControllers.add(midiQwertyKeys = new SCMidiInput(SCMidiInput.KEYS)); - midiControllers.add(midiQwertyAPC = new SCMidiInput(SCMidiInput.APC)); + grid = new GridController(this); + midiControllers.add(midiQwertyKeys = new VirtualKeyMidiInput(this, VirtualKeyMidiInput.KEYS)); + midiControllers.add(midiQwertyAPC = new VirtualKeyMidiInput(this, VirtualKeyMidiInput.APC)); for (MidiInputDevice device : RWMidi.getInputDevices()) { if (device.getName().contains("APC")) { - midiControllers.add(new APC40MidiInput(device).setEnabled(true)); + midiControllers.add(new APC40MidiInput(this, device).setEnabled(true)); } else if (device.getName().contains("SLIDER/KNOB KORG")) { - midiControllers.add(new KorgNanoKontrolMidiInput(device).setEnabled(true)); + midiControllers.add(new KorgNanoKontrolMidiInput(this, device).setEnabled(true)); } else { boolean enabled = device.getName().contains("KEYBOARD KORG") || device.getName().contains("Bus 1 Apple"); - midiControllers.add(new SCMidiInput(device).setEnabled(enabled)); + midiControllers.add(new GenericDeviceMidiInput(this, device).setEnabled(enabled)); } } for (MidiOutputDevice device : RWMidi.getOutputDevices()) { @@ -65,6 +66,14 @@ class MidiEngine { return this.midiControllers; } + public Engine.Deck getFocusedDeck() { + return lx.engine.getDeck(activeDeckIndex); + } + + public SCPattern getFocusedPattern() { + return (SCPattern) getFocusedDeck().getActivePattern(); + } + public MidiEngine setFocusedDeck(int deckIndex) { if (this.activeDeckIndex != deckIndex) { this.activeDeckIndex = deckIndex; @@ -75,10 +84,6 @@ class MidiEngine { return this; } - public Engine.Deck getFocusedDeck() { - return lx.engine.getDeck(activeDeckIndex); - } - public boolean isQwertyEnabled() { return midiQwertyKeys.isEnabled() || midiQwertyAPC.isEnabled(); } @@ -88,30 +93,20 @@ public interface SCMidiInputListener { public void onEnabled(SCMidiInput controller, boolean enabled); } -public class SCMidiInput extends AbstractScrollItem { +public abstract class SCMidiInput extends AbstractScrollItem { - public static final int MIDI = 0; - public static final int KEYS = 1; - public static final int APC = 2; - - private boolean enabled = false; + protected boolean enabled = false; private final String name; - private final int mode; - private int octaveShift = 0; - - class NoteMeta { - int channel; - int number; - NoteMeta(int channel, int number) { - this.channel = channel; - this.number = number; - } - } - final Map keyToNote = new HashMap(); + protected final MidiEngine midiEngine; final List listeners = new ArrayList(); + protected SCMidiInput(MidiEngine midiEngine, String name) { + this.midiEngine = midiEngine; + this.name = name; + } + public SCMidiInput addListener(SCMidiInputListener l) { listeners.add(l); return this; @@ -122,25 +117,127 @@ public class SCMidiInput extends AbstractScrollItem { return this; } - SCMidiInput(MidiInputDevice d) { - mode = MIDI; - d.createInput(this); - name = d.getName().replace("Unknown vendor",""); + public String getLabel() { + return name; + } + + public boolean isEnabled() { + return enabled; + } + + public boolean isSelected() { + return enabled; + } + + public void onMousePressed() { + setEnabled(!enabled); + } + + public SCMidiInput setEnabled(boolean enabled) { + if (enabled != this.enabled) { + this.enabled = enabled; + for (SCMidiInputListener l : listeners) { + l.onEnabled(this, enabled); + } + } + return this; + } + + private boolean logMidi() { + return (uiMidi != null) && uiMidi.logMidi(); } - SCMidiInput(int mode) { + final void programChangeReceived(ProgramChange pc) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Program Change :: " + pc.getNumber()); + } + handleProgramChange(pc); + } + + final void controllerChangeReceived(rwmidi.Controller cc) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Controller :: " + cc.getChannel() + " :: " + cc.getCC() + ":" + cc.getValue()); + } + if (!handleGridControllerChange(cc)) { + if (!midiEngine.getFocusedPattern().controllerChange(cc)) { + handleControllerChange(cc); + } + } + } + + final void noteOnReceived(Note note) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Note On :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); + } + if (!handleGridNoteOn(note)) { + if (!midiEngine.getFocusedPattern().noteOn(note)) { + handleNoteOn(note); + } + } + } + + final void noteOffReceived(Note note) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Note Off :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); + } + if (!handleGridNoteOff(note)) { + if (!midiEngine.getFocusedPattern().noteOff(note)) { + handleNoteOff(note); + } + } + } + + // Subclasses may implement these to map top-level functionality + protected boolean handleGridNoteOn(Note note) { return false; } + protected boolean handleGridNoteOff(Note note) { return false; } + protected boolean handleGridControllerChange(rwmidi.Controller cc) { return false; } + protected void handleProgramChange(ProgramChange pc) {} + protected void handleControllerChange(rwmidi.Controller cc) {} + protected void handleNoteOn(Note note) {} + protected void handleNoteOff(Note note) {} +} + +public class VirtualKeyMidiInput extends SCMidiInput { + + public static final int KEYS = 1; + public static final int APC = 2; + + private final int mode; + + private int octaveShift = 0; + + class NoteMeta { + int channel; + int number; + NoteMeta(int channel, int number) { + this.channel = channel; + this.number = number; + } + } + + final Map keyToNote = new HashMap(); + + VirtualKeyMidiInput(MidiEngine midiEngine, int mode) { + super(midiEngine, "QWERTY (" + (mode == APC ? "APC" : "Key") + " Mode)"); this.mode = mode; - switch (mode) { - case APC: - name = "QWERTY (APC Mode)"; + if (mode == APC) { mapAPC(); - break; - default: - case KEYS: - name = "QWERTY (Key Mode)"; + } else { mapKeys(); - break; } + registerKeyEvent(this); } private void mapAPC() { @@ -168,7 +265,6 @@ public class SCMidiInput extends AbstractScrollItem { mapNote('v', 3, 56); mapNote('b', 4, 56); mapNote('n', 5, 56); - registerKeyEvent(this); } private void mapKeys() { @@ -188,17 +284,12 @@ public class SCMidiInput extends AbstractScrollItem { mapNote('k', 1, note++); mapNote('o', 1, note++); mapNote('l', 1, note++); - registerKeyEvent(this); } void mapNote(char ch, int channel, int number) { keyToNote.put(ch, new NoteMeta(channel, number)); } - - public String getLabel() { - return name; - } - + public void keyEvent(KeyEvent e) { if (!enabled) { return; @@ -226,101 +317,56 @@ public class SCMidiInput extends AbstractScrollItem { } } } +} - public boolean isEnabled() { - return enabled; - } - - public boolean isSelected() { - return enabled; - } - - public void onMousePressed() { - setEnabled(!enabled); - } - - public SCMidiInput setEnabled(boolean enabled) { - if (enabled != this.enabled) { - this.enabled = enabled; - for (SCMidiInputListener l : listeners) { - l.onEnabled(this, enabled); - } - } - return this; +public class GenericDeviceMidiInput extends SCMidiInput { + GenericDeviceMidiInput(MidiEngine midiEngine, MidiInputDevice d) { + super(midiEngine, d.getName().replace("Unknown vendor","")); + d.createInput(this); } +} - protected SCPattern getFocusedPattern() { - return (SCPattern) midiEngine.getFocusedDeck().getActivePattern(); - } +public class APC40MidiInput extends GenericDeviceMidiInput { - private boolean logMidi() { - return (uiMidi != null) && uiMidi.logMidi(); + private boolean shiftOn = false; + private LXEffect releaseEffect = null; + + APC40MidiInput(MidiEngine midiEngine, MidiInputDevice d) { + super(midiEngine, d); } - final void programChangeReceived(ProgramChange pc) { - if (!enabled) { - return; + private class GridPosition { + public final int row, col; + GridPosition(int r, int c) { + row = r; + col = c; } - if (logMidi()) { - println(getLabel() + " :: Program Change :: " + pc.getNumber()); - } - handleProgramChange(pc); } - - final void controllerChangeReceived(rwmidi.Controller cc) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Controller :: " + cc.getCC() + ":" + cc.getValue()); - } - if (!getFocusedPattern().controllerChangeReceived(cc)) { - handleControllerChange(cc); + + private GridPosition getGridPosition(Note note) { + int channel = note.getChannel(); + int pitch = note.getPitch(); + if (channel < 8) { + if (pitch >= 53 && pitch <=57) return new GridPosition(pitch-53, channel); + else if (pitch == 52) return new GridPosition(5, channel); } + return null; } - final void noteOnReceived(Note note) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Note On :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); - } - if (!getFocusedPattern().noteOnReceived(note)) { - handleNoteOn(note); + protected boolean handleGridNoteOn(Note note) { + GridPosition p = getGridPosition(note); + if (p != null) { + return midiEngine.grid.gridPressed(p.row, p.col); } + return false; } - final void noteOffReceived(Note note) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Note Off :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); + protected boolean handleGridNoteOff(Note note) { + GridPosition p = getGridPosition(note); + if (p != null) { + return midiEngine.grid.gridReleased(p.row, p.col); } - if (!getFocusedPattern().noteOffReceived(note)) { - handleNoteOff(note); - } - } - - // Subclasses may implement these to map top-level functionality - protected void handleProgramChange(ProgramChange pc) { - } - protected void handleControllerChange(rwmidi.Controller cc) { - } - protected void handleNoteOn(Note note) { - } - protected void handleNoteOff(Note note) { - } -} - -public class APC40MidiInput extends SCMidiInput { - - private boolean shiftOn = false; - private LXEffect releaseEffect = null; - - APC40MidiInput(MidiInputDevice d) { - super(d); + return false; } protected void handleControllerChange(rwmidi.Controller cc) { @@ -339,7 +385,7 @@ public class APC40MidiInput extends SCMidiInput { parameterIndex = 8 + (number-16); } if (parameterIndex >= 0) { - List parameters = getFocusedPattern().getParameters(); + List parameters = midiEngine.getFocusedPattern().getParameters(); if (parameterIndex < parameters.size()) { parameters.get(parameterIndex).setValue(cc.getValue() / 127.); } @@ -463,17 +509,17 @@ public class APC40MidiInput extends SCMidiInput { } } -class KorgNanoKontrolMidiInput extends SCMidiInput { +class KorgNanoKontrolMidiInput extends GenericDeviceMidiInput { - KorgNanoKontrolMidiInput(MidiInputDevice d) { - super(d); + KorgNanoKontrolMidiInput(MidiEngine midiEngine, MidiInputDevice d) { + super(midiEngine, d); } protected void handleControllerChange(rwmidi.Controller cc) { int number = cc.getCC(); if (number >= 16 && number <= 23) { int parameterIndex = number - 16; - List parameters = getFocusedPattern().getParameters(); + List parameters = midiEngine.getFocusedPattern().getParameters(); if (parameterIndex < parameters.size()) { parameters.get(parameterIndex).setValue(cc.getValue() / 127.); } @@ -502,7 +548,7 @@ class KorgNanoKontrolMidiInput extends SCMidiInput { } } -class APC40MidiOutput implements LXParameter.Listener { +class APC40MidiOutput implements LXParameter.Listener, GridOutput { private final MidiEngine midiEngine; private final MidiOutput output; @@ -531,6 +577,7 @@ class APC40MidiOutput implements LXParameter.Listener { d.addListener(deckListener); } resetParameters(); + midiEngine.grid.addOutput(this); } private void resetParameters() { @@ -557,6 +604,11 @@ class APC40MidiOutput implements LXParameter.Listener { while (i < 12) { sendKnob(i++, 0); } + for (int row = 0; row < 7; ++row) { + for (int col = 0; col < 8; ++col) { + setGridState(row, col, 0); + } + } } private void resetEffectParameters() { @@ -610,4 +662,53 @@ class APC40MidiOutput implements LXParameter.Listener { ++i; } } + + public void setGridState(int row, int col, int state) { + if (col < 8) { + if (row < 5) output.sendNoteOn(col, 53+row, state); + else if (row == 6) output.sendNoteOn(col, 52, state); + } + } +} + +interface GridOutput { + public static final int OFF = 0; + public static final int GREEN = 1; + public static final int GREEN_BLINK = 2; + public static final int RED = 3; + public static final int RED_BLINK = 4; + public static final int YELLOW = 5; + public static final int YELLOW_BLINK = 6; + public static final int ON = 127; + + public void setGridState(int row, int col, int state); +} + +class GridController { + private final List outputs = new ArrayList(); + + private final MidiEngine midiEngine; + + GridController(MidiEngine midiEngine) { + this.midiEngine = midiEngine; + } + + public void addOutput(GridOutput output) { + outputs.add(output); + } + + public boolean gridPressed(int row, int col) { + return midiEngine.getFocusedPattern().gridPressed(row, col); + } + + public boolean gridReleased(int row, int col) { + return midiEngine.getFocusedPattern().gridReleased(row, col); + } + + public void setState(int row, int col, int state) { + for (GridOutput g : outputs) { + g.setGridState(row, col, state); + } + } } +