LXPattern[] patterns;
MappingTool mappingTool;
PandaDriver[] pandaBoards;
-final List<MidiListener> midiListeners = new ArrayList<MidiListener>();
+MidiListener midiQwerty;
// Display configuration mode
boolean mappingMode = false;
UIContext[] overlays;
UIPatternDeck uiPatternA;
UICrossfader uiCrossfader;
+UIMidi uiMidi;
UIMapping uiMapping;
UIDebugText uiDebugText;
}
mappingTool = new MappingTool(glucose, pandaMappings);
logTime("Built PandaDriver");
-
+
+ // MIDI devices
+ List<MidiListener> midiListeners = new ArrayList<MidiListener>();
+ midiListeners.add(midiQwerty = new MidiListener());
+ for (MidiInputDevice device : RWMidi.getInputDevices()) {
+ boolean enableDevice = device.getName().contains("APC");
+ midiListeners.add(new MidiListener(device).setEnabled(enableDevice));
+ }
+ SCMidiDevices.initializeStandardDevices(glucose);
+ logTime("Setup MIDI devices");
+
// Build overlay UI
debugUI = new DebugUI(pandaMappings);
overlays = new UIContext[] {
- uiPatternA = new UIPatternDeck(lx.engine.getDeck(0), "PATTERN A", 4, 4, 140, 344),
- uiCrossfader = new UICrossfader(4, 352, 140, 212),
- new UIOutput(4, 568, 140, 106),
+ uiPatternA = new UIPatternDeck(lx.engine.getDeck(0), "PATTERN A", 4, 4, 140, 324),
+ new UIBlendMode(4, 332, 140, 86),
+ new UIEffects(4, 422, 140, 144),
+ new UITempo(4, 570, 140, 50),
+ new UISpeed(4, 624, 140, 50),
+
+ new UIPatternDeck(lx.engine.getDeck(1), "PATTERN B", width-144, 4, 140, 324),
+ uiMidi = new UIMidi(midiListeners, width-144, 332, 140, 136),
+ new UIOutput(width-144, 472, 140, 106),
- new UIPatternDeck(lx.engine.getDeck(1), "PATTERN B", width-144, 4, 140, 344),
- new UIEffects(width-144, 352, 140, 144),
- new UITempo(width-144, 498, 140, 50),
- new UISpeed(width-144, 552, 140, 50),
+ uiCrossfader = new UICrossfader(width/2-90, height-90, 180, 86),
- uiDebugText = new UIDebugText(4, height-64, width-8, 44),
- uiMapping = new UIMapping(mappingTool, 4, 4, 140, 344),
+ uiDebugText = new UIDebugText(148, height-138, width-304, 44),
+ uiMapping = new UIMapping(mappingTool, 4, 4, 140, 324),
};
uiMapping.setVisible(false);
logTime("Built overlay UI");
- // MIDI devices
- midiListeners.add(new MidiListener().setEnabled(true));
- for (MidiInputDevice d : RWMidi.getInputDevices()) {
- midiListeners.add(new MidiListener(d));
- }
- SCMidiDevices.initializeStandardDevices(glucose);
- logTime("Setup MIDI devices");
-
// Setup camera
midX = TRAILER_WIDTH/2.;
midY = glucose.model.yMax/2;
println("Hit the 'p' key to toggle Panda Board output");
}
-public class MidiListener {
+public class MidiListener extends AbstractScrollItem {
private boolean enabled = false;
private final String name;
name = d.getName();
}
+ class NoteMeta {
+ int channel;
+ int number;
+ NoteMeta(int channel, int number) {
+ this.channel = channel;
+ this.number = number;
+ }
+ }
+
+ final Map<Character, NoteMeta> keyToNote = new HashMap<Character, NoteMeta>();
+
MidiListener() {
+ name = "QWERTY Keyboard";
+ mapNote('1', 0, 53);
+ mapNote('2', 1, 53);
+ mapNote('3', 2, 53);
+ mapNote('4', 3, 53);
+ mapNote('5', 4, 53);
+ mapNote('6', 5, 53);
+ mapNote('q', 0, 54);
+ mapNote('w', 1, 54);
+ mapNote('e', 2, 54);
+ mapNote('r', 3, 54);
+ mapNote('t', 4, 54);
+ mapNote('y', 5, 54);
+ mapNote('a', 0, 55);
+ mapNote('s', 1, 55);
+ mapNote('d', 2, 55);
+ mapNote('f', 3, 55);
+ mapNote('g', 4, 55);
+ mapNote('h', 5, 55);
+ mapNote('z', 0, 56);
+ mapNote('x', 1, 56);
+ mapNote('c', 2, 56);
+ mapNote('v', 3, 56);
+ mapNote('b', 4, 56);
+ mapNote('n', 5, 56);
registerKeyEvent(this);
- name = "Keyboard";
}
- public String getName() {
+ 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 (e.getID() == KeyEvent.KEY_PRESSED) {
- switch (e.getKeyChar()) {
- case 'q':
- noteOnReceived(new Note(60, 127));
+ char c = Character.toLowerCase(e.getKeyChar());
+ NoteMeta nm = keyToNote.get(c);
+ if (nm != null) {
+ switch (e.getID()) {
+ case KeyEvent.KEY_PRESSED:
+ noteOnReceived(new Note(Note.NOTE_ON, nm.channel, nm.number, 127));
break;
- }
- } else if (e.getID() == KeyEvent.KEY_RELEASED) {
- switch (e.getKeyChar()) {
- case 'q':
- noteOffReceived(new Note(60, 0));
+ case KeyEvent.KEY_RELEASED:
+ noteOffReceived(new Note(Note.NOTE_OFF, nm.channel, nm.number, 0));
break;
}
}
}
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public boolean isSelected() {
+ return enabled;
+ }
+
+ public void onMousePressed() {
+ setEnabled(!enabled);
+ }
+
public MidiListener setEnabled(boolean enabled) {
if (enabled != this.enabled) {
this.enabled = enabled;
- // notify midi UI to update
+ uiMidi.redraw();
}
return this;
}
+ private SCPattern getFocusedPattern() {
+ return (SCPattern) uiMidi.getFocusedDeck().getActivePattern();
+ }
+
+ void programChangeReceived(ProgramChange pc) {
+ if (!enabled) {
+ return;
+ }
+ println("PC: " + pc.toString());
+ }
+
void controllerChangeReceived(rwmidi.Controller cc) {
if (!enabled) {
return;
}
println("CC: " + cc.toString());
+ getFocusedPattern().controllerChangeReceived(cc);
}
void noteOnReceived(Note note) {
return;
}
println("Note On: " + note.toString());
+ getFocusedPattern().noteOnReceived(note);
+
}
void noteOffReceived(Note note) {
return;
}
println("Note Off: " + note.toString());
+ getFocusedPattern().noteOffReceived(note);
}
}
0, -1, 0
);
- translate(0, 10, 0);
+ translate(0, 40, 0);
noStroke();
fill(#141414);
frameRate(++targetFramerate);
break;
case 'd':
- debugMode = !debugMode;
- println("Debug output: " + (debugMode ? "ON" : "OFF"));
+ if (!midiQwerty.isEnabled()) {
+ debugMode = !debugMode;
+ println("Debug output: " + (debugMode ? "ON" : "OFF"));
+ }
break;
case 'm':
- mappingMode = !mappingMode;
- uiPatternA.setVisible(!mappingMode);
- uiMapping.setVisible(mappingMode);
- if (mappingMode) {
- restoreToPattern = lx.getPattern();
- lx.setPatterns(new LXPattern[] { mappingTool });
- } else {
- lx.setPatterns(patterns);
- LXTransition pop = restoreToPattern.getTransition();
- restoreToPattern.setTransition(null);
- lx.goPattern(restoreToPattern);
- restoreToPattern.setTransition(pop);
+ if (!midiQwerty.isEnabled()) {
+ mappingMode = !mappingMode;
+ uiPatternA.setVisible(!mappingMode);
+ uiMapping.setVisible(mappingMode);
+ if (mappingMode) {
+ restoreToPattern = lx.getPattern();
+ lx.setPatterns(new LXPattern[] { mappingTool });
+ } else {
+ lx.setPatterns(patterns);
+ LXTransition pop = restoreToPattern.getTransition();
+ restoreToPattern.setTransition(null);
+ lx.goPattern(restoreToPattern);
+ restoreToPattern.setTransition(pop);
+ }
}
break;
case 'p':
for (LXPattern p : deck.getPatterns()) {
items.add(new PatternScrollItem(p));
}
- final UIScrollList patternList = new UIScrollList(1, yp, w-2, 160).setItems(items);
+ final UIScrollList patternList = new UIScrollList(1, yp, w-2, 140).setItems(items);
patternList.addToContainer(this);
yp += patternList.h + 10;
}
}
-class UICrossfader extends UIWindow {
-
- private final UIToggleSet displayMode;
-
- public UICrossfader(float x, float y, float w, float h) {
- super("CROSSFADER", x, y, w, h);
-
+class UIBlendMode extends UIWindow {
+ public UIBlendMode(float x, float y, float w, float h) {
+ super("BLEND MODE", x, y, w, h);
List<ScrollItem> items = new ArrayList<ScrollItem>();
for (LXTransition t : glucose.getTransitions()) {
items.add(new TransitionScrollItem(t));
}
final UIScrollList tList;
- (tList = new UIScrollList(1, titleHeight, w-2, 120)).setItems(items).addToContainer(this);
- new UIParameterSlider(4, titleHeight + 126, w-10, 24).setParameter(lx.engine.getDeck(1).getCrossfader()).addToContainer(this);
- (displayMode = new UIToggleSet(4, 182, w-10, 20)).setOptions(new String[] { "A", "COMP", "B" }).setValue("COMP").addToContainer(this);
-
+ (tList = new UIScrollList(1, titleHeight, w-2, 60)).setItems(items).addToContainer(this);
+
lx.engine.getDeck(1).addListener(new Engine.AbstractListener() {
public void blendTransitionDidChange(Engine.Deck deck, LXTransition transition) {
tList.redraw();
}
});
}
-
- public String getDisplayMode() {
- return displayMode.getValue();
+
+ class TransitionScrollItem extends AbstractScrollItem {
+ private final LXTransition transition;
+ private String label;
+
+ TransitionScrollItem(LXTransition transition) {
+ this.transition = transition;
+ label = className(transition, "Transition");
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public boolean isSelected() {
+ return transition == glucose.getSelectedTransition();
+ }
+
+ public boolean isPending() {
+ return false;
+ }
+
+ public void onMousePressed() {
+ glucose.setSelectedTransition(transition);
+ }
}
+
}
-class TransitionScrollItem extends AbstractScrollItem {
- private final LXTransition transition;
- private String label;
-
- TransitionScrollItem(LXTransition transition) {
- this.transition = transition;
- label = className(transition, "Transition");
- }
-
- public String getLabel() {
- return label;
- }
+class UICrossfader extends UIWindow {
- public boolean isSelected() {
- return transition == glucose.getSelectedTransition();
- }
+ private final UIToggleSet displayMode;
- public boolean isPending() {
- return false;
+ public UICrossfader(float x, float y, float w, float h) {
+ super("CROSSFADER", x, y, w, h);
+
+ new UIParameterSlider(4, titleHeight, w-9, 32).setParameter(lx.engine.getDeck(1).getCrossfader()).addToContainer(this);
+ (displayMode = new UIToggleSet(4, titleHeight + 36, w-9, 20)).setOptions(new String[] { "A", "COMP", "B" }).setValue("COMP").addToContainer(this);
}
- public void onMousePressed() {
- glucose.setSelectedTransition(transition);
+ public String getDisplayMode() {
+ return displayMode.getValue();
}
}
}).setRange(1, glucose.model.cubes.size()).addToContainer(this);
yp += 24;
- new UILabel(4, yp+8, w-10, 20).setLabel("COLORS").addToContainer(this);
- yp += 24;
-
+ yp += 10;
+
new UIScrollList(1, yp, w-2, 60).setItems(Arrays.asList(new ScrollItem[] {
new ColorScrollItem(ColorScrollItem.COLOR_RED),
new ColorScrollItem(ColorScrollItem.COLOR_GREEN),
return false;
}
- public void select() {
+ public void onMousePressed() {
switch (colorChannel) {
case COLOR_RED: mappingTool.channelModeRed = !mappingTool.channelModeRed; break;
case COLOR_GREEN: mappingTool.channelModeGreen = !mappingTool.channelModeGreen; break;
pg.fill(#444444);
pg.rect(0, 0, w, h);
pg.textFont(defaultItemFont);
+ pg.textSize(10);
pg.textAlign(LEFT, TOP);
pg.fill(#cccccc);
pg.text(line1, 4, 4);
}
}
+class UIMidi extends UIWindow {
+
+ final private UIToggleSet deckMode;
+
+ UIMidi(List<MidiListener> midiListeners, float x, float y, float w, float h) {
+ super("MIDI", x, y, w, h);
+ // Processing compiler doesn't seem to get that list of class objects also conform to interface
+ List<ScrollItem> scrollItems = new ArrayList<ScrollItem>();
+ for (MidiListener ml : midiListeners) {
+ scrollItems.add(ml);
+ }
+ new UIScrollList(1, titleHeight, w-2, 80).setItems(scrollItems).addToContainer(this);
+ (deckMode = new UIToggleSet(4, 110, w-9, 20)).setOptions(new String[] { "A", "B" }).addToContainer(this);
+ }
+
+ public Engine.Deck getFocusedDeck() {
+ return lx.engine.getDeck(deckMode.getValue() == "A" ? 0 : 1);
+ }
+}
+
String className(Object p, String suffix) {
String s = p.getClass().getName();
int li;