diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/ClipSceneCursor.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/ClipSceneCursor.java index e7ab1f4a..ae019966 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/ClipSceneCursor.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/ClipSceneCursor.java @@ -30,10 +30,9 @@ public ClipSceneCursor(final ControllerHost host, final NavigationState navigati sceneBank = singleTrackBank.sceneBank(); sceneBank.cursorIndex().markInterested(); sceneBank.setIndication(false); - singleTrackBank.canScrollChannelsUp().addValueObserver(v -> navigationState.setCanGoTrackLeft(v)); - singleTrackBank.canScrollChannelsDown().addValueObserver(v -> navigationState.setCanGoTrackRight(v)); - sceneBank.canScrollBackwards().addValueObserver(v -> navigationState.setCanScrollSceneUp(v)); - sceneBank.canScrollForwards().addValueObserver(v -> navigationState.setCanScrollSceneDown(v)); + singleTrackBank.canScrollChannelsDown().addValueObserver(navigationState::setCanGoTrackRight); + sceneBank.canScrollBackwards().addValueObserver(navigationState::setCanScrollSceneUp); + sceneBank.canScrollForwards().addValueObserver(navigationState::setCanScrollSceneDown); } public CursorTrack getCursorTrack() { diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/DataStringUtil.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/DataStringUtil.java index 9e180859..5d0d1ddc 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/DataStringUtil.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/DataStringUtil.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; public class DataStringUtil { @@ -13,7 +12,7 @@ public static String toString(final byte[] data) { for (final byte d : data) { values.add("%02x".formatted(d)); } - return values.stream().collect(Collectors.joining()); + return String.join("", values); } public static byte[] toTempo10nsData(final double tempo) { @@ -31,7 +30,6 @@ public static double toTempo(final int[] data) { for (int i = 0; i < 5; i++) { nsPerMinute |= (long) data[i] << (i * 7); } - final double bpm = TEN_NS_PER_MINUTE / nsPerMinute; - return bpm; + return TEN_NS_PER_MINUTE / nsPerMinute; } } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolAExtension.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolAExtension.java index 1582b6d5..3f5bebc8 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolAExtension.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolAExtension.java @@ -48,7 +48,8 @@ public void init() { final MidiIn midiIn2 = host.getMidiInPort(1); final NoteInput noteInput = midiIn2.createNoteInput( - "MIDI", "80????", "90????", "D0????", "E0????", "B001??", "B040??", "B042??", "B1????"); + "MIDI", "80????", "90????", "D0????", "E0????", "B001??", "B040??", "B042??", + "B1????"); noteInput.setShouldConsumeEvents(true); initTrackBank(); @@ -115,7 +116,7 @@ protected void initNavigation() { final ModeButton knobPressed = controlElements.getKnobPressed(); final ModeButton knobShiftPressed = controlElements.getKnobShiftPressed(); - mainLayer.bindPressed(knobPressed.getHwButton(), () -> clipSceneCursor.launch()); + mainLayer.bindPressed(knobPressed.getHwButton(), clipSceneCursor::launch); mainLayer.bindPressed(knobShiftPressed.getHwButton(), () -> handle4DShiftPressed(rootTrack, cursorTrack)); } @@ -125,11 +126,6 @@ protected void initJogWheel() { mainLayer.bind(fourKnob, midiProcessor.createIncAction(this::handleTransportScroll)); } - @Override - public void exit() { - midiProcessor.exit(); - } - @Override public void flush() { midiProcessor.doFlush(); @@ -148,9 +144,7 @@ protected void setUpChannelControl(final int index, final Track channel) { }); channel.exists().markInterested(); - channel.addIsSelectedInMixerObserver(v -> { - midiProcessor.sendValueCommand(ValueCommand.SELECT, index, v); - }); + channel.addIsSelectedInMixerObserver(v -> midiProcessor.sendValueCommand(ValueCommand.SELECT, index, v)); channel.mute().addValueObserver(v -> midiProcessor.sendValueCommand(ValueCommand.MUTE, index, v)); channel.solo().addValueObserver(v -> midiProcessor.sendValueCommand(ValueCommand.SOLO, index, v)); channel.arm().addValueObserver(v -> midiProcessor.sendValueCommand(ValueCommand.ARM, index, v)); diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolExtension.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolExtension.java index 7cfc169f..f9fe571a 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolExtension.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolExtension.java @@ -46,8 +46,6 @@ public abstract class KompleteKontrolExtension extends ControllerExtension { static final String KONTAKT_8_VST3_ID = "5653544E694B386B6F6E74616B742038"; static final String MASCHINE_3_VST3_ID = "5653544E694D336D61736368696E6520"; - private static final DateTimeFormatter DF = DateTimeFormatter.ofPattern("hh:mm:ss SSS"); - protected HardwareSurface surface; private final List knobBindings = new ArrayList<>(); diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolSMk2Extension.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolSMk2Extension.java index 3e9c0dda..646784d1 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolSMk2Extension.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KompleteKontrolSMk2Extension.java @@ -70,7 +70,6 @@ public void setUpChannelDisplayFeedback(final int index, final Track channel) { @Override protected void initNavigation() { - KompleteKontrolExtension.println(" INIT NAVIGATION"); final Clip cursorClip = getHost().createLauncherCursorClip(8, 128); final Clip arrangerClip = getHost().createArrangerCursorClip(8, 128); @@ -127,20 +126,13 @@ protected void initNavigation() { .setValueSupplier(() -> cursorTrack.canHoldNoteData().get() && cursorClip.exists().get()); final ModeButton knobPressed = controlElements.getKnobPressed(); final ModeButton knobShiftPressed = controlElements.getKnobShiftPressed(); - mainLayer.bindPressed(knobPressed.getHwButton(), () -> clipSceneCursor.launch()); + mainLayer.bindPressed(knobPressed.getHwButton(), clipSceneCursor::launch); mainLayer.bindPressed(knobShiftPressed.getHwButton(), () -> handle4DShiftPressed(rootTrack, cursorTrack)); } - - @Override - public void exit() { - midiProcessor.exit(); - } - @Override public void flush() { midiProcessor.doFlush(); } - } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KontrolSMk3Extension.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KontrolSMk3Extension.java index 7a5bdc69..3db6528a 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KontrolSMk3Extension.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/KontrolSMk3Extension.java @@ -12,6 +12,7 @@ import com.bitwig.extension.controller.api.ScrollbarModel; import com.bitwig.extension.controller.api.SettableBeatTimeValue; import com.bitwig.extension.controller.api.Track; +import com.bitwig.extensions.controllers.nativeinstruments.komplete.binding.EncoderParameterBinding; import com.bitwig.extensions.controllers.nativeinstruments.komplete.control.ModeButton; import com.bitwig.extensions.controllers.nativeinstruments.komplete.definition.AbstractKompleteKontrolExtensionDefinition; import com.bitwig.extensions.controllers.nativeinstruments.komplete.device.DeviceControl; @@ -69,10 +70,16 @@ public void init() { } protected void initScrubZoomControl() { - final RelativeHardwareKnob fourDKnob = controlElements.getFourDKnobMixer(); + final RelativeHardwareKnob fourDKnob = controlElements.getFourDKnob(); final RelativeHardwarControlBindable binding = midiProcessor.createIncAction(this::handleFourDInc); mainLayer.bind(fourDKnob, binding); + final CursorTrack cursorTrack = viewControl.getCursorTrack(); + final RelativeHardwareKnob daw4dKnob = controlElements.getFourDKnobMixer(); + mainLayer.addBinding(new EncoderParameterBinding(daw4dKnob, cursorTrack.volume())); + final RelativeHardwareKnob daw4dPan = controlElements.getFourDKnobPan(); + mainLayer.addBinding(new EncoderParameterBinding(daw4dPan, cursorTrack.pan())); + final RelativeHardwareKnob loopKnob = controlElements.getLoopModKnob(); mainLayer.bind(loopKnob, midiProcessor.createIncAction(this::handleLoop)); } @@ -218,15 +225,9 @@ private void handleLayoutChange(final String v) { midiProcessor.sendLayoutCommand(currentLayoutType); } - @Override - public void exit() { - midiProcessor.exit(); - } - @Override public void flush() { midiProcessor.doFlush(); } - } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/LayoutType.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/LayoutType.java index 7163cae5..0f4e662e 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/LayoutType.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/LayoutType.java @@ -1,22 +1,22 @@ package com.bitwig.extensions.controllers.nativeinstruments.komplete; public enum LayoutType { - LAUNCHER("MIX"), // - ARRANGER("ARRANGE"); - - private String name; - - LayoutType(final String name) { - this.name = name; - } - - public static LayoutType toType(final String layoutName) { - for (final LayoutType layoutType : LayoutType.values()) { - if (layoutType.name.equals(layoutName)) { - return layoutType; - } - } - return LAUNCHER; - } - + LAUNCHER("MIX"), // + ARRANGER("ARRANGE"); + + private final String name; + + LayoutType(final String name) { + this.name = name; + } + + public static LayoutType toType(final String layoutName) { + for (final LayoutType layoutType : LayoutType.values()) { + if (layoutType.name.equals(layoutName)) { + return layoutType; + } + } + return LAUNCHER; + } + } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/NavigationState.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/NavigationState.java index bd0c68a7..eeb5f74c 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/NavigationState.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/NavigationState.java @@ -3,49 +3,31 @@ public class NavigationState { private boolean canScrollSceneDown = false; private boolean canScrollSceneUp = false; - private boolean canGoTrackLeft = false; private boolean canGoTrackRight = false; protected boolean sceneNavMode = false; - private Runnable stateChangeHandler; - public void setStateChangeListener(final Runnable stateChange) { - this.stateChangeHandler = stateChange; - fireStateChange(); - } public void setCanScrollSceneDown(final boolean canScrollSceneDown) { this.canScrollSceneDown = canScrollSceneDown; - fireStateChange(); } public void setCanScrollSceneUp(final boolean canScrollSceneUp) { this.canScrollSceneUp = canScrollSceneUp; - fireStateChange(); } - public void setCanGoTrackLeft(final boolean canGoTrackLeft) { - this.canGoTrackLeft = canGoTrackLeft; - fireStateChange(); - } public void setCanGoTrackRight(final boolean canGoTrackRight) { this.canGoTrackRight = canGoTrackRight; - fireStateChange(); } public void setSceneNavMode(final boolean sceneNavMode) { this.sceneNavMode = sceneNavMode; - fireStateChange(); } public boolean isSceneNavMode() { return sceneNavMode; } - public boolean canGoTrackLeft() { - return canGoTrackLeft; - } - public boolean canGoTrackRight() { return canGoTrackRight; } @@ -58,18 +40,4 @@ public boolean canScrollSceneUp() { return canScrollSceneUp; } - public int getSceneValue() { - return (canScrollSceneDown ? 0x2 : 0x0) | (canScrollSceneUp ? 0x1 : 0x0); - } - - public int getTrackValue() { - return (!sceneNavMode ? 0x1 : 0x0) | (canGoTrackRight ? 0x2 : 0x0); - } - - private void fireStateChange() { - if (stateChangeHandler == null) { - return; - } - stateChangeHandler.run(); - } } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/TrackType.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/TrackType.java index 102d5fc7..822cef73 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/TrackType.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/TrackType.java @@ -4,32 +4,32 @@ * The track types as recognized by KK. */ public enum TrackType { - NONE(0, ""), // - UNSPECIFIED(1, "Unspec"), // - INSTRUMENT(2, "Instrument"), // - AUDIO(3, "Audio"), // - GROUP(4, "Group"), // - RETURN_BUS(5, "Effect"), // - MASTER(6, "Master"); // - - private int id; - private String type; - - private TrackType(final int id, final String type) { - this.id = id; - this.type = type; - } - - public int getId() { - return id; - } - - public static TrackType toType(final String type) { - for (final TrackType trackType : TrackType.values()) { - if (trackType.type.equals(type)) { - return trackType; - } - } - return UNSPECIFIED; - } + NONE(0, ""), // + UNSPECIFIED(1, "Unspec"), // + INSTRUMENT(2, "Instrument"), // + AUDIO(3, "Audio"), // + GROUP(4, "Group"), // + RETURN_BUS(5, "Effect"), // + MASTER(6, "Master"); // + + private final int id; + private final String type; + + TrackType(final int id, final String type) { + this.id = id; + this.type = type; + } + + public int getId() { + return id; + } + + public static TrackType toType(final String type) { + for (final TrackType trackType : TrackType.values()) { + if (trackType.type.equals(type)) { + return trackType; + } + } + return UNSPECIFIED; + } } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/binding/EncoderParameterBinding.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/binding/EncoderParameterBinding.java new file mode 100644 index 00000000..e02e68b5 --- /dev/null +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/binding/EncoderParameterBinding.java @@ -0,0 +1,37 @@ +package com.bitwig.extensions.controllers.nativeinstruments.komplete.binding; + +import com.bitwig.extension.controller.api.HardwareBinding; +import com.bitwig.extension.controller.api.Parameter; +import com.bitwig.extension.controller.api.RelativeHardwareControlBinding; +import com.bitwig.extension.controller.api.RelativeHardwareKnob; +import com.bitwig.extension.controller.api.SettableRangedValue; +import com.bitwig.extensions.framework.Binding; + +public class EncoderParameterBinding extends Binding { + public static final double BASE_SENSITIVITY = 1; + + private HardwareBinding hwBinding; + + public EncoderParameterBinding(final RelativeHardwareKnob encoder, final Parameter parameter) { + super(encoder, encoder, parameter); + } + + protected RelativeHardwareControlBinding getHardwareBinding(final double sensitivity) { + return getTarget().addBindingWithSensitivity(getSource(), sensitivity); + } + + @Override + protected void deactivate() { + if (hwBinding != null && isActive()) { + hwBinding.removeBinding(); + } + } + + @Override + protected void activate() { + if (hwBinding != null) { + hwBinding.removeBinding(); + } + hwBinding = getHardwareBinding(BASE_SENSITIVITY); + } +} diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/ControlElements.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/ControlElements.java index b2c7f716..6bbad1dc 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/ControlElements.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/ControlElements.java @@ -36,6 +36,7 @@ public class ControlElements { private final HardwareSurface surface; private final RelativeHardwareKnob fourDKnob; private final RelativeHardwareKnob loopModKnob; + private final RelativeHardwareKnob fourDKnobPan; private final Map modeButtons = new HashMap<>(); private final KontrolLightButton leftNavButton; @@ -56,9 +57,9 @@ public ControlElements(final HardwareSurface surface, final MidiProcessor midiPr Arrays.stream(CcAssignment.values()) // .filter(CcAssignment::isMapped) // - .forEach(ccAssignment -> { - modeButtons.put(ccAssignment, new ModeButton(midiProcessor, ccAssignment.getName(), ccAssignment)); - }); + .forEach(ccAssignment -> modeButtons.put( + ccAssignment, + new ModeButton(midiProcessor, ccAssignment.getName(), ccAssignment))); muteSelectedButton = surface.createHardwareButton("MUTE_SELECTED_BUTTON"); muteSelectedButton.pressedAction().setActionMatcher(CcAssignment.MUTE_CURRENT.createActionMatcher(midiIn, 1)); @@ -80,6 +81,10 @@ public ControlElements(final HardwareSurface surface, final MidiProcessor midiPr fourDKnobMixer.setAdjustValueMatcher(midiIn.createRelative2sComplementCCValueMatcher(0xF, 0x64, 4096)); fourDKnobMixer.setStepSize(1 / 128.0); + fourDKnobPan = surface.createRelativeHardwareKnob("4D_WHEEL_MIX_MODE_PAN"); + fourDKnobPan.setAdjustValueMatcher(midiIn.createRelative2sComplementCCValueMatcher(0xF, 0x65, 4096)); + fourDKnobPan.setStepSize(1 / 128.0); + fourDKnob = surface.createRelativeHardwareKnob("4D_WHEEL_PLUGIN_MODE"); fourDKnob.setAdjustValueMatcher(midiIn.createRelative2sComplementCCValueMatcher(0xF, 0x34, 128)); fourDKnob.setStepSize(1 / 128.0); @@ -101,7 +106,7 @@ public ControlElements(final HardwareSurface surface, final MidiProcessor midiPr } private HardwareButton createOnOffButton(final String name, final int ccNr) { - final HardwareButton button = surface.createHardwareButton("SHIFT_BUTTON"); + final HardwareButton button = surface.createHardwareButton(name); button.pressedAction().setActionMatcher(midiProcessor.getMidiIn().createCCActionMatcher(0xF, ccNr, 1)); button.releasedAction().setActionMatcher(midiProcessor.getMidiIn().createCCActionMatcher(0xF, ccNr, 0)); return button; @@ -156,6 +161,10 @@ public RelativeHardwareKnob getFourDKnobMixer() { return fourDKnobMixer; } + public RelativeHardwareKnob getFourDKnobPan() { + return fourDKnobPan; + } + public RelativeHardwareKnob getLoopModKnob() { return loopModKnob; } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/KontrolLightButton.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/KontrolLightButton.java index fb74137d..13a02495 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/KontrolLightButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/control/KontrolLightButton.java @@ -57,10 +57,6 @@ public HardwareButton getHwButton() { return hwButton; } - public OnOffHardwareLight getHwLight() { - return hwLight; - } - public void bindPressed(final Layer layer, final Runnable action) { layer.bindPressed(hwButton, action); } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/definition/AbstractKompleteKontrolExtensionDefinition.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/definition/AbstractKompleteKontrolExtensionDefinition.java index d689fbbb..cbb4aa7c 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/definition/AbstractKompleteKontrolExtensionDefinition.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/definition/AbstractKompleteKontrolExtensionDefinition.java @@ -27,7 +27,7 @@ public String getAuthor() { @Override public String getVersion() { - return "1.5"; + return "2.0"; } @Override diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BankControl.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BankControl.java index 1a8fc49e..6b935e6b 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BankControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BankControl.java @@ -11,7 +11,6 @@ public class BankControl { - private final DeviceBank deviceBank; private final MidiProcessor midiProcessor; private final List devices = new ArrayList<>(); @@ -29,8 +28,7 @@ public class BankControl { private boolean trackRemotesPresent; private boolean projectRemotesPresent; - private class ParentTab implements DeviceSelectionTab { - + private static class ParentTab implements DeviceSelectionTab { @Override public String getLayerCode() { return "[<< Parent]"; @@ -45,7 +43,7 @@ public enum Focus { public BankControl(final PinnableCursorDevice cursorDevice, final MidiProcessor midiProcessor, final DeviceControl deviceControl) { - this.deviceBank = cursorDevice.deviceChain().createDeviceBank(64); + final DeviceBank deviceBank = cursorDevice.deviceChain().createDeviceBank(64); this.midiProcessor = midiProcessor; this.deviceControl = deviceControl; this.cursorDevice = cursorDevice; diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BrowserHandler.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BrowserHandler.java index 3415c367..02ca6763 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BrowserHandler.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/BrowserHandler.java @@ -1,7 +1,6 @@ package com.bitwig.extensions.controllers.nativeinstruments.komplete.device; import com.bitwig.extension.controller.api.BooleanValue; -import com.bitwig.extension.controller.api.BrowserResultsColumn; import com.bitwig.extension.controller.api.ControllerHost; import com.bitwig.extension.controller.api.CursorDevice; import com.bitwig.extension.controller.api.InsertionPoint; @@ -11,22 +10,17 @@ public class BrowserHandler { private final PopupBrowser browser; private boolean browserOpen; - private final CursorDevice device; private boolean deviceExists; private final InsertionPoint insertionPoint; - private final ControllerHost host; private final BooleanValue shiftHeld; public BrowserHandler(final ControllerHost host, final CursorDevice device, final BooleanValue shiftHeld) { - this.host = host; this.browser = host.createPopupBrowser(); this.browser.exists().addValueObserver(this::handleExists); - this.device = device; - this.device.exists().addValueObserver(this::handleDeviceExists); + device.exists().addValueObserver(this::handleDeviceExists); insertionPoint = device.replaceDeviceInsertionPoint(); this.shiftHeld = shiftHeld; browser.shouldAudition().markInterested(); - final BrowserResultsColumn resultsColum = browser.resultsColumn(); } private void handleDeviceExists(final boolean exists) { diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceControl.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceControl.java index 23e25b1a..d3a19fa5 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceControl.java @@ -8,7 +8,6 @@ import com.bitwig.extension.controller.api.RelativeHardwareKnob; import com.bitwig.extension.controller.api.SettableEnumValue; import com.bitwig.extension.controller.api.Track; -import com.bitwig.extensions.controllers.nativeinstruments.komplete.KompleteKontrolExtension; import com.bitwig.extensions.controllers.nativeinstruments.komplete.ViewControl; import com.bitwig.extensions.controllers.nativeinstruments.komplete.control.ControlElements; import com.bitwig.extensions.controllers.nativeinstruments.komplete.control.ModeButton; @@ -20,7 +19,6 @@ public class DeviceControl implements DeviceMidiListener { - private final BrowserHandler browserHandler; public static final String ONLY_DEVICES = "only Devices"; public static final String WITH_TRACK_PROJECT = "with Track/Project"; private final MidiProcessor midiProcessor; @@ -29,13 +27,7 @@ public class DeviceControl implements DeviceMidiListener { private Runnable bankUpdateTask = null; private final Layer navigationLayer; - private final PinnableCursorDevice cursorDevice; private final ControlElements controlElements; - private final Layer deviceRemoteLayer; - private final Layer trackRemoteLayer; - private final Layer projectRemoteLayer; - private final Layer directParamLayer; - private final Layer browserNavLayer; private boolean directActive; private final DirectParameterControl directParameterControl; @@ -53,25 +45,26 @@ public DeviceControl(final ControllerHost host, final MidiProcessor midiProcesso this.midiProcessor.addDeviceMidiListener(this); this.midiProcessor.addModeListener(this::changeMode); navigationLayer = new Layer(layers, "PARAM_NAVIGATION_LAYER"); - deviceRemoteLayer = new Layer(layers, "DEVICE"); - trackRemoteLayer = new Layer(layers, "TRACK"); - projectRemoteLayer = new Layer(layers, "PROJECT"); - directParamLayer = new Layer(layers, "DIRECT_PARAM"); - browserNavLayer = new Layer(layers, "BROWSER_NAV"); + final Layer deviceRemoteLayer = new Layer(layers, "DEVICE"); + final Layer trackRemoteLayer = new Layer(layers, "TRACK"); + final Layer projectRemoteLayer = new Layer(layers, "PROJECT"); + final Layer directParamLayer = new Layer(layers, "DIRECT_PARAM"); + final Layer browserNavLayer = new Layer(layers, "BROWSER_NAV"); final CursorTrack cursorTrack = viewControl.getClipSceneCursor().getCursorTrack(); this.host = host; this.controlElements = controlElements; - cursorDevice = cursorTrack.createCursorDevice(); + final PinnableCursorDevice cursorDevice = cursorTrack.createCursorDevice(); cursorDevice.presetName().addValueObserver(this::handlePresetName); this.mainBank = new BankControl(cursorDevice, this.midiProcessor, this); this.mainBank.getCurrentFocus().addValueObserver(this::handleFocus); - browserHandler = new BrowserHandler(host, cursorDevice, controlElements.getShiftHeld()); + final BrowserHandler browserHandler = new BrowserHandler(host, cursorDevice, controlElements.getShiftHeld()); final CursorRemoteControlsPage deviceRemotePages = cursorDevice.createCursorRemoteControlsPage(8); deviceRemotesControl = new RemotesControl(deviceRemoteLayer, deviceRemotePages, controlElements, midiProcessor); directParameterControl = new DirectParameterControl( - directParamLayer, cursorDevice, controlElements, midiProcessor, deviceRemotePages.pageCount()); + directParamLayer, cursorDevice, controlElements, midiProcessor, + deviceRemotePages.pageCount()); directParameterControl.getDirectActive().addValueObserver(this::handleDirectActive); final Track rootTrack = viewControl.getProject().getRootTrackGroup(); @@ -107,16 +100,15 @@ public DeviceControl(final ControllerHost host, final MidiProcessor midiProcesso trackRemotes.pageCount().addValueObserver(this::handleTrackPages); projectRemotes.pageCount().addValueObserver(this::handleProjectPages); - browserHandler.isOpen().addValueObserver(browserOpen -> browserNavLayer.setIsActive(browserOpen)); + browserHandler.isOpen().addValueObserver(browserNavLayer::setIsActive); final ModeButton knobPressed = controlElements.getKnobPressed(); final ModeButton knobShiftPressed = controlElements.getKnobShiftPressed(); - final RelativeHardwareKnob fourDKnob = controlElements.getFourDKnobMixer(); + final RelativeHardwareKnob fourDKnob = controlElements.getFourDKnob(); browserNavLayer.bindPressed(knobPressed.getHwButton(), browserHandler::confirm); browserNavLayer.bindPressed(knobShiftPressed.getHwButton(), browserHandler::cancel); final RelativeHardwarControlBindable binding = midiProcessor.createIncAction( new ConditionalIntDecelerator(browserHandler::incrementSelection, 10, controlElements.getShiftHeld(), 10)); browserNavLayer.bind(fourDKnob, binding); - //cursorTrack.channelIndex().addValueObserver(this::handleTrackIndexChange); controlElements.getLeftNavButton() .bind(browserNavLayer, this::handleBrowserLeftNavigation, this::browserNavigationState); @@ -169,9 +161,7 @@ private void handleFocus(final BankControl.Focus focus) { this.deviceFocus = focus; this.currentRemotesControl.setActive(false); switch (this.deviceFocus) { - case DEVICE -> { - currentRemotesControl = directActive ? directParameterControl : deviceRemotesControl; - } + case DEVICE -> currentRemotesControl = directActive ? directParameterControl : deviceRemotesControl; case TRACK -> currentRemotesControl = trackRemotesControl; case PROJECT -> currentRemotesControl = projectRemotesControl; } @@ -183,8 +173,6 @@ private void initSetting(final ControllerHost host) { "Remotes", // "Visible", new String[] {ONLY_DEVICES, WITH_TRACK_PROJECT}, ONLY_DEVICES); useTrackRemotes.addValueObserver(value -> this.useRemotes.set(value.equals(WITH_TRACK_PROJECT))); - KompleteKontrolExtension.println( - " INIT %s - %s", useTrackRemotes.get(), useTrackRemotes.get().equals(WITH_TRACK_PROJECT)); this.useRemotes.set(useTrackRemotes.get().equals(WITH_TRACK_PROJECT)); } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceSlot.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceSlot.java index 48bf5c68..4910f3be 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceSlot.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DeviceSlot.java @@ -13,19 +13,17 @@ public class DeviceSlot implements DeviceSelectionTab { private final int index; private boolean hasLayers; private boolean hasDrumPads; - private boolean isNested; private boolean isExpanded; private final Device device; private boolean selected; - private DeviceLayerBank layerBank; private final List layerSlots = new ArrayList<>(); public DeviceSlot(final int index, final Device device) { this.index = index; this.device = device; if (this.device != null) { - this.layerBank = device.createLayerBank(64); + final DeviceLayerBank layerBank = device.createLayerBank(64); for (int i = 0; i < layerBank.getSizeOfBank(); i++) { final LayerSlot layerSlot = new LayerSlot(i, layerBank.getItemAt(i)); layerSlots.add(layerSlot); @@ -77,14 +75,6 @@ public void setHasDrumPads(final boolean hasDrumPads) { this.hasDrumPads = hasDrumPads; } - public void setExpanded(final boolean expanded) { - this.isExpanded = expanded; - } - - public boolean isExpanded() { - return isExpanded; - } - public boolean isSelected() { return selected; } @@ -101,7 +91,7 @@ public String getLayerCode() { if (isExpanded) { return "{\"n\":\"%s\",\"c\":[%s]}".formatted( name, - getLayerList().stream().map(v -> "\"%s\"".formatted(v)).collect(Collectors.joining(","))); + getLayerList().stream().map("\"%s\""::formatted).collect(Collectors.joining(","))); } else { return "{\"n\":\"%s\",\"c\":[]}".formatted(name); } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectParameterControl.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectParameterControl.java index 8cdb1268..db2701d3 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectParameterControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectParameterControl.java @@ -180,7 +180,7 @@ private void handleParameterIds(final String[] ids) { } } pageCount.set((assigned + 7) / 8); - final String[] idsToObserve = observed.stream().toArray(String[]::new); + final String[] idsToObserve = observed.toArray(String[]::new); midiProcessor.delay(() -> parameterObserver.setObservedParameterIds(idsToObserve), 50); applySlotsToIndex(); } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectSlot.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectSlot.java index 1350ea77..21fd4f1e 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectSlot.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/DirectSlot.java @@ -48,11 +48,6 @@ public String getParamId() { return paramId; } - public String getBaseParam() { - final int last = paramId.lastIndexOf("/"); - return paramId.substring(last + 1); - } - public String getInParamId() { if (paramId != null && paramId.startsWith(ID_PREFIX)) { return "%sROOT_GENERIC_MODULE/%s".formatted(ID_PREFIX, paramId.substring(ID_PREFIX.length())); diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/LayerSlot.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/LayerSlot.java index 77dcd95b..4667cb2b 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/LayerSlot.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/LayerSlot.java @@ -6,20 +6,16 @@ class LayerSlot { private final DeviceLayer layer; - private final DeviceBank bank; private final Device device; private final int index; private boolean exists; private String name; - private boolean deviceExists; - private final int layerCount = 0; public LayerSlot(final int index, final DeviceLayer layer) { this.layer = layer; this.index = index; - this.bank = layer.createDeviceBank(1); + final DeviceBank bank = layer.createDeviceBank(1); this.device = bank.getDevice(0); - this.device.exists().addValueObserver(exists -> this.deviceExists = exists); this.layer.exists().addValueObserver(this::handleExists); this.layer.name().addValueObserver(this::handleName); } @@ -60,11 +56,4 @@ public void setName(final String name) { this.name = name; } - public boolean isDeviceExists() { - return deviceExists; - } - - public void setDeviceExists(final boolean deviceExists) { - this.deviceExists = deviceExists; - } } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/ParameterSlot.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/ParameterSlot.java deleted file mode 100644 index 1392bcd6..00000000 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/ParameterSlot.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.bitwig.extensions.controllers.nativeinstruments.komplete.device; - -import com.bitwig.extension.controller.api.RelativeHardwareControlBinding; -import com.bitwig.extension.controller.api.RemoteControl; - -public class ParameterSlot { - - private final int index; - private final RemoteControl parameter; - private String name = ""; - private boolean exists; - private double origin; - private int discreteSteps; - private final RelativeHardwareControlBinding binding; - private boolean onPlugin; - - public ParameterSlot(final int index, final RemoteControl parameter, final RelativeHardwareControlBinding binding) { - this.index = index; - this.parameter = parameter; - this.binding = binding; - } - - public RemoteControl getParameter() { - return parameter; - } - - public int getIndex() { - return index; - } - - public String getName() { - return name; - } - - public int getType() { - if (origin == 0.5) { - return 1; - } - if (discreteSteps == 2) { - return 2; - } - if (discreteSteps > 2 && discreteSteps < 16) { - return 3; - } - return 0; - } - - public void setName(final String name) { - this.name = name; - } - - public boolean isExists() { - return exists; - } - - public void setExists(final boolean exists) { - this.exists = exists; - } - - public void setOnPlugin(final boolean onPlugin) { - this.onPlugin = onPlugin; - setSensitivity(); - } - - public void setValueCount(final int values) { - this.discreteSteps = values; - setSensitivity(); - } - - public void setOrigin(final double origin) { - this.origin = origin; - } - - private void setSensitivity() { - if (discreteSteps < 1 || onPlugin) { - binding.setSensitivity(0.4); - } else { - final double sens = Math.min(0.005 * discreteSteps, 0.4); - binding.setSensitivity(sens); - } - } - - public void applyFineAdjust(final boolean shift) { - if (discreteSteps < 1) { - binding.setSensitivity(shift ? 0.125 : 0.4); - } - } -} diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/RemotesControl.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/RemotesControl.java index 9950e639..4122d7b4 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/RemotesControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/device/RemotesControl.java @@ -17,7 +17,6 @@ public class RemotesControl extends AbstractParameterControl { private int pageCount; private int pageIndex; private String[] pageNames = new String[0]; - private final String name; final CursorRemoteControlsPage deviceRemotes; private final List bindings = new ArrayList<>(); final MidiProcessor midiProcessor; @@ -28,7 +27,6 @@ public RemotesControl(final Layer layer, final CursorRemoteControlsPage remotes, super(layer); this.deviceRemotes = remotes; this.midiProcessor = midiProcessor; - this.name = layer.getName(); remotes.selectedPageIndex().addValueObserver(this::handlePageIndex); remotes.pageCount().addValueObserver(this::handlePageCount); for (int i = 0; i < 8; i++) { diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/MidiProcessor.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/MidiProcessor.java index f91e46b5..fd9c59c4 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/MidiProcessor.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/MidiProcessor.java @@ -34,6 +34,7 @@ public class MidiProcessor { private final ControllerHost host; private boolean dawModeConfirmed; private String lastReportedKKInstance = null; + private int expectedProtocol; private final HardwareSurface surface; private final List deviceListeners = new ArrayList<>(); private final List modeListener = new ArrayList<>(); @@ -75,6 +76,11 @@ private void handleSysex(final String sysExData) { } } + public void intoDawMode(final int protocol) { + this.expectedProtocol = protocol; + midiOut.sendMidi(0xBF, 0x1, protocol); + } + public void delay(final Runnable action, final int delay) { host.scheduleTask(action, delay); } @@ -94,9 +100,7 @@ public void exit() { protected void onMidi0(final ShortMidiMessage msg) { if (msg.getStatusByte() == 0xBF) { if (msg.getData1() == 1) { - KompleteKontrolExtension.println(" DAW MODE = %d", msg.getData2()); - dawModeConfirmed = true; - sendDawInfo(5, 3); + handleHandshakeComplete(msg); } else if (msg.getData1() == 5) { modeListener.forEach(listener -> listener.accept(msg.getData2())); } else { @@ -109,6 +113,18 @@ protected void onMidi0(final ShortMidiMessage msg) { } } + private void handleHandshakeComplete(final ShortMidiMessage msg) { + dawModeConfirmed = true; + if (msg.getData2() != expectedProtocol) { + if (expectedProtocol == 4) { + host.showPopupNotification("Please update Kontrol S Mk3 firmware to version 2.0 or higher"); + } else { + host.showPopupNotification("Please update firmware to higher version"); + } + } + sendDawInfo(5, 3); + } + public RelativeHardwarControlBindable createIncDoubleAction(final DoubleConsumer changeAction) { return host.createRelativeHardwareControlAdjustmentTarget(changeAction); } @@ -195,10 +211,6 @@ public void sendSelectionIndex(final int index, final int[] subindexes) { ValueCommand.SELECTION_INDEX.send(midiOut, index, subindexes); } - public void intoDawMode(final int protocol) { - midiOut.sendMidi(0xBF, 0x1, protocol); - } - public void sendLedUpdate(final CcAssignment assignment, final int value) { midiOut.sendMidi(0xBF, assignment.getStateId(), value); } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/NhiaSyexLevelsCommand.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/NhiaSyexLevelsCommand.java index 84c533ca..6ccc5b7b 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/NhiaSyexLevelsCommand.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/komplete/midi/NhiaSyexLevelsCommand.java @@ -3,32 +3,27 @@ import com.bitwig.extension.controller.api.MidiOut; public class NhiaSyexLevelsCommand extends NhiaSysexCommand { - - private final byte[] levelsArray; - - public NhiaSyexLevelsCommand(final int commandId) { - levelsArray = new byte[BASE_FORMAT.length + 16]; - System.arraycopy(BASE_FORMAT, 0, levelsArray, 0, BASE_FORMAT.length); - levelsArray[10] = (byte) commandId; - levelsArray[11] = 2; - levelsArray[12] = 0; - levelsArray[levelsArray.length - 1] = SYSEX_END; - } - - public void updateLevel(final int track, final int levelLeft, final int levelRight) { - levelsArray[13 + track * 2] = (byte) levelLeft; - levelsArray[14 + track * 2] = (byte) levelRight; - } - - public void updateLeft(final int track, final int levelLeft) { - levelsArray[13 + track * 2] = (byte) levelLeft; - } - - public void updateRight(final int track, final int levelRight) { - levelsArray[14 + track * 2] = (byte) levelRight; - } - - public void update(final MidiOut midiOut) { - midiOut.sendSysex(levelsArray); - } + + private final byte[] levelsArray; + + public NhiaSyexLevelsCommand(final int commandId) { + levelsArray = new byte[BASE_FORMAT.length + 16]; + System.arraycopy(BASE_FORMAT, 0, levelsArray, 0, BASE_FORMAT.length); + levelsArray[10] = (byte) commandId; + levelsArray[11] = 2; + levelsArray[12] = 0; + levelsArray[levelsArray.length - 1] = SYSEX_END; + } + + public void updateLeft(final int track, final int levelLeft) { + levelsArray[13 + track * 2] = (byte) levelLeft; + } + + public void updateRight(final int track, final int levelRight) { + levelsArray[14 + track * 2] = (byte) levelRight; + } + + public void update(final MidiOut midiOut) { + midiOut.sendSysex(levelsArray); + } } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/LaunchViewControl.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/LaunchViewControl.java index d5dd0a95..fc1f6317 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/LaunchViewControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/LaunchViewControl.java @@ -1,68 +1,91 @@ package com.bitwig.extensions.controllers.novation.launchcontrolxlmk3; -import com.bitwig.extension.controller.api.*; +import com.bitwig.extension.controller.api.ControllerHost; +import com.bitwig.extension.controller.api.CursorTrack; +import com.bitwig.extension.controller.api.PinnableCursorDevice; +import com.bitwig.extension.controller.api.SendBank; +import com.bitwig.extension.controller.api.Track; +import com.bitwig.extension.controller.api.TrackBank; import com.bitwig.extensions.framework.di.Component; @Component public class LaunchViewControl { - - private final TrackBank trackBank; - private final CursorTrack cursorTrack; - private final SendBank refSendBank; - private final PinnableCursorDevice cursorDevice; - private final Track rootTrack; - - public LaunchViewControl(final ControllerHost host) { - trackBank = host.createTrackBank(8, 2, 1); - refSendBank = trackBank.getItemAt(0).sendBank(); - for (int i = 0; i < 8; i++) { - prepareTrack(trackBank.getItemAt(i)); - } - cursorTrack = host.createCursorTrack(8, 1); - prepareTrack(cursorTrack); - trackBank.followCursorTrack(cursorTrack); - - cursorDevice = cursorTrack.createCursorDevice(); - - rootTrack = host.getProject().getRootTrackGroup(); - - cursorTrack.hasNext().markInterested(); - cursorTrack.hasPrevious().markInterested(); - } - - public TrackBank getTrackBank() { - return trackBank; - } - - public CursorTrack getCursorTrack() { - return cursorTrack; - } - - public Track getRootTrack() { - return rootTrack; - } - - public PinnableCursorDevice getCursorDevice() { - return cursorDevice; - } - - public SendBank getRefSendBank() { - return refSendBank; - } - - public void navigateSends(final int dir) { - for (int i = 0; i < 8; i++) { - final Track track = trackBank.getItemAt(i); - track.sendBank().scrollBy(dir); - } - } - - private void prepareTrack(final Track track) { - track.arm().markInterested(); - track.mute().markInterested(); - track.solo().markInterested(); - track.sourceSelector().hasAudioInputSelected().markInterested(); - track.sourceSelector().hasNoteInputSelected().markInterested(); - } - + + private final TrackBank trackBank; + private final CursorTrack cursorTrack; + private final SendBank refSendBank; + private final PinnableCursorDevice cursorDevice; + private final Track rootTrack; + private final TrackBank singleTrackBank; + private final Track singleTrack; + + public LaunchViewControl(final ControllerHost host) { + trackBank = host.createTrackBank(8, 2, 1); + refSendBank = trackBank.getItemAt(0).sendBank(); + for (int i = 0; i < 8; i++) { + prepareTrack(trackBank.getItemAt(i)); + } + cursorTrack = host.createCursorTrack(8, 1); + prepareTrack(cursorTrack); + trackBank.followCursorTrack(cursorTrack); + + cursorDevice = cursorTrack.createCursorDevice(); + + rootTrack = host.getProject().getRootTrackGroup(); + + cursorTrack.hasNext().markInterested(); + cursorTrack.hasPrevious().markInterested(); + singleTrackBank = host.createTrackBank(1, 0, 1); + singleTrackBank.scrollPosition().markInterested(); + singleTrackBank.itemCount().markInterested(); + singleTrackBank.cursorIndex().markInterested(); + singleTrackBank.followCursorTrack(cursorTrack); + singleTrack = singleTrackBank.getItemAt(0); + } + + public TrackBank getTrackBank() { + return trackBank; + } + + public CursorTrack getCursorTrack() { + return cursorTrack; + } + + public Track getRootTrack() { + return rootTrack; + } + + public PinnableCursorDevice getCursorDevice() { + return cursorDevice; + } + + public SendBank getRefSendBank() { + return refSendBank; + } + + public void navigateSends(final int dir) { + for (int i = 0; i < 8; i++) { + final Track track = trackBank.getItemAt(i); + track.sendBank().scrollBy(dir); + } + } + + private void prepareTrack(final Track track) { + track.arm().markInterested(); + track.mute().markInterested(); + track.solo().markInterested(); + track.sourceSelector().hasAudioInputSelected().markInterested(); + track.sourceSelector().hasNoteInputSelected().markInterested(); + } + + public void navigateCursorBy(final int inc) { + singleTrackBank.scrollBy(inc); + singleTrack.selectInEditor(); + singleTrack.selectInMixer(); + } + + public boolean canScrollBy(final int inc) { + final int index = singleTrackBank.cursorIndex().get() + inc; + return index >= 0 && index < singleTrackBank.itemCount().get(); + } } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/Remotes.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/Remotes.java index 25fc2d5a..683866a8 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/Remotes.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/Remotes.java @@ -1,5 +1,8 @@ package com.bitwig.extensions.controllers.novation.launchcontrolxlmk3.layer; +import java.util.ArrayList; +import java.util.List; + import com.bitwig.extension.controller.api.CursorDevice; import com.bitwig.extension.controller.api.CursorRemoteControlsPage; import com.bitwig.extension.controller.api.Parameter; @@ -13,138 +16,137 @@ import com.bitwig.extensions.framework.Layer; import com.bitwig.extensions.framework.values.BasicStringValue; -import java.util.ArrayList; -import java.util.List; - class Remotes { - public static final List DEVICE_COLORS = - List.of( - GradientColor.RED, GradientColor.ORANGE, GradientColor.YELLOW, GradientColor.GREEN, - GradientColor.DARK_GREEN, GradientColor.BLUE, GradientColor.PURPLE, GradientColor.PINK); - - private String[] devicePageNames; - private int devicePageIndex = 0; - private int devicePage2Index = 0; - private int devicePageCount = 0; - private boolean active; - private final BasicStringValue devicePageName = new BasicStringValue(); - private final CursorRemoteControlsPage remotes; - private final CursorRemoteControlsPage remotes2; - private final BasicStringValue deviceName = new BasicStringValue(""); - private final List disableBindings = new ArrayList<>(); - - public Remotes(final CursorDevice cursorDevice) { - this.remotes = cursorDevice.createCursorRemoteControlsPage(8); - this.remotes2 = cursorDevice.createCursorRemoteControlsPage("PAGE2", 8, null); - remotes.pageNames().addValueObserver(this::handleDevicePages); - remotes.selectedPageIndex().addValueObserver(this::handleDevicePageIndex); - remotes.pageCount().addValueObserver(this::updatePageCount); - remotes2.selectedPageIndex().addValueObserver(this::handleDevicePage2Index); - cursorDevice.name().addValueObserver(deviceName::set); - } - - private void handleDevicePage2Index(final int index) { - devicePage2Index = index; - updateDevicePageName(true); - } - - public void bind(final Layer layer, final LaunchControlXlHwElements hwElements, - final DisplayControl displayControl) { - for (int i = 0; i < 8; i++) { - final LaunchRelativeEncoder row1Encoder = hwElements.getRelativeEncoder(0, i); - final LaunchRelativeEncoder row2Encoder = hwElements.getRelativeEncoder(1, i); - final Parameter parameter = this.getParameter(i); - layer.addBinding( - new RelativeEncoderBinding(parameter, row1Encoder, displayControl, deviceName, parameter.name())); - layer.addBinding(new LightValueBindings(parameter, row1Encoder.getLight(), DEVICE_COLORS.get(i))); - final Parameter parameter2 = getParameter2(i); - - final RelativeEncoderBinding row2Binding = - new RelativeEncoderBinding(parameter2, row2Encoder, displayControl, deviceName, parameter2.name()); - layer.addBinding(row2Binding); - final LightValueBindings row2LightBinding = - new LightValueBindings(parameter2, row2Encoder.getLight(), DEVICE_COLORS.get(i)); - layer.addBinding(row2LightBinding); - disableBindings.add(row2Binding); - disableBindings.add(row2LightBinding); - } - } - - private void updatePageCount(final int count) { - this.devicePageCount = count; - updateRow2Layer(); - if (devicePageIndex == devicePage2Index && devicePageCount > 1) { - if (devicePageIndex + 1 < this.devicePageCount) { - this.devicePage2Index = devicePageIndex + 1; - } else { - this.devicePage2Index = 0; - } - this.remotes2.selectedPageIndex().set(devicePage2Index); - } - } - - private void updateRow2Layer() { - final boolean isRow2Active = active && devicePageCount > 1 && devicePageIndex + 1 < devicePageCount; - disableBindings.forEach(binding -> binding.setDisabled(!isRow2Active)); - } - - private void handleDevicePages(final String[] pages) { - this.devicePageNames = pages; - updateDevicePageName(true); - } - - private void handleDevicePageIndex(final int selectedPageIndex) { - this.devicePageIndex = selectedPageIndex; - final int page2Index = selectedPageIndex + 1 < devicePageCount ? selectedPageIndex + 1 : 0; - this.remotes2.selectedPageIndex().set(page2Index); - devicePage2Index = page2Index; - updateRow2Layer(); - updateDevicePageName(false); - } - - private void updateDevicePageName(final boolean handleEmpty) { - if (this.devicePageNames != null && devicePageIndex < this.devicePageNames.length && devicePageIndex != -1) { - if (devicePageIndex == devicePage2Index || devicePageIndex + 1 >= devicePageNames.length - || devicePage2Index == -1) { - this.devicePageName.set(this.devicePageNames[devicePageIndex]); - } else { - this.devicePageName.set( - "%s/%s".formatted(devicePageNames[devicePageIndex], devicePageNames[devicePage2Index])); - } - } else if (handleEmpty) { - this.devicePageName.set("No Page"); - } - } - - public void setActive(final boolean active) { - this.active = active; - } - - public Parameter getParameter(final int index) { - return remotes.getParameter(index); - } - - public Parameter getParameter2(final int index) { - return remotes2.getParameter(index); - } - - public BasicStringValue getDevicePageName() { - return devicePageName; - } - - public boolean canGoBack() { - return devicePageIndex > 0; - } - - public boolean canGoForward() { - return devicePageNames != null && devicePageNames.length > 0 && devicePageIndex != devicePageCount - 1; - } - - public void selectPreviousPage() { - this.remotes.selectPreviousPage(false); - } - - public void selectNextPage() { - this.remotes.selectNextPage(false); - } + public static final List DEVICE_COLORS = + List.of( + GradientColor.RED, GradientColor.ORANGE, GradientColor.YELLOW, GradientColor.GREEN, + GradientColor.DARK_GREEN, GradientColor.BLUE, GradientColor.PURPLE, GradientColor.PINK); + + private String[] devicePageNames; + private int devicePageIndex = 0; + private int devicePage2Index = 0; + private int devicePageCount = 0; + private boolean active; + private final BasicStringValue devicePageName = new BasicStringValue(); + private final CursorRemoteControlsPage remotes; + private final CursorRemoteControlsPage remotes2; + private final BasicStringValue deviceName = new BasicStringValue(""); + private final List disableBindings = new ArrayList<>(); + + public Remotes(final CursorDevice cursorDevice) { + this.remotes = cursorDevice.createCursorRemoteControlsPage(8); + this.remotes2 = cursorDevice.createCursorRemoteControlsPage("PAGE2", 8, null); + remotes.pageNames().addValueObserver(this::handleDevicePages); + remotes.selectedPageIndex().addValueObserver(this::handleDevicePageIndex); + remotes.pageCount().addValueObserver(this::updatePageCount); + remotes2.selectedPageIndex().addValueObserver(this::handleDevicePage2Index); + cursorDevice.name().addValueObserver(deviceName::set); + } + + private void handleDevicePage2Index(final int index) { + devicePage2Index = index; + updateDevicePageName(true); + } + + public void bind(final Layer layer, final LaunchControlXlHwElements hwElements, + final DisplayControl displayControl) { + for (int i = 0; i < 8; i++) { + final LaunchRelativeEncoder row1Encoder = hwElements.getRelativeEncoder(0, i); + final LaunchRelativeEncoder row2Encoder = hwElements.getRelativeEncoder(1, i); + final Parameter parameter = this.getParameter(i); + layer.addBinding( + new RelativeEncoderBinding(parameter, row1Encoder, displayControl, deviceName, parameter.name())); + layer.addBinding(new LightValueBindings(parameter, row1Encoder.getLight(), DEVICE_COLORS.get(i))); + final Parameter parameter2 = getParameter2(i); + + final RelativeEncoderBinding row2Binding = + new RelativeEncoderBinding(parameter2, row2Encoder, displayControl, deviceName, parameter2.name()); + layer.addBinding(row2Binding); + final LightValueBindings row2LightBinding = + new LightValueBindings(parameter2, row2Encoder.getLight(), DEVICE_COLORS.get(i)); + layer.addBinding(row2LightBinding); + disableBindings.add(row2Binding); + disableBindings.add(row2LightBinding); + } + } + + private void updatePageCount(final int count) { + this.devicePageCount = count; + updateRow2Layer(); + if (devicePageIndex == devicePage2Index && devicePageCount > 1) { + if (devicePageIndex + 1 < this.devicePageCount) { + this.devicePage2Index = devicePageIndex + 1; + } else { + this.devicePage2Index = 0; + } + this.remotes2.selectedPageIndex().set(devicePage2Index); + } + } + + private void updateRow2Layer() { + final boolean isRow2Active = active && devicePageCount > 1 && devicePageIndex + 1 < devicePageCount; + disableBindings.forEach(binding -> binding.setDisabled(!isRow2Active)); + } + + private void handleDevicePages(final String[] pages) { + this.devicePageNames = pages; + updateDevicePageName(true); + } + + private void handleDevicePageIndex(final int selectedPageIndex) { + this.devicePageIndex = selectedPageIndex; + final int page2Index = selectedPageIndex + 1 < devicePageCount ? selectedPageIndex + 1 : 0; + this.remotes2.selectedPageIndex().set(page2Index); + devicePage2Index = page2Index; + updateRow2Layer(); + updateDevicePageName(false); + } + + private void updateDevicePageName(final boolean handleEmpty) { + if (this.devicePageNames != null && devicePageIndex < this.devicePageNames.length && devicePageIndex != -1) { + if (devicePageIndex == devicePage2Index || devicePageIndex + 1 >= devicePageNames.length + || devicePage2Index == -1) { + this.devicePageName.set(this.devicePageNames[devicePageIndex]); + } else { + this.devicePageName.set( + "%s/%s".formatted( + devicePageNames[Math.min(devicePageIndex, devicePageNames.length - 1)], + devicePageNames[Math.min(devicePage2Index, devicePageNames.length - 1)])); + } + } else if (handleEmpty) { + this.devicePageName.set("No Page"); + } + } + + public void setActive(final boolean active) { + this.active = active; + } + + public Parameter getParameter(final int index) { + return remotes.getParameter(index); + } + + public Parameter getParameter2(final int index) { + return remotes2.getParameter(index); + } + + public BasicStringValue getDevicePageName() { + return devicePageName; + } + + public boolean canGoBack() { + return devicePageIndex > 0; + } + + public boolean canGoForward() { + return devicePageNames != null && devicePageNames.length > 0 && devicePageIndex != devicePageCount - 1; + } + + public void selectPreviousPage() { + this.remotes.selectPreviousPage(false); + } + + public void selectNextPage() { + this.remotes.selectNextPage(false); + } } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/TransportHandler.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/TransportHandler.java index 901f85e8..9ae8fcae 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/TransportHandler.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchcontrolxlmk3/layer/TransportHandler.java @@ -1,6 +1,11 @@ package com.bitwig.extensions.controllers.novation.launchcontrolxlmk3.layer; -import com.bitwig.extension.controller.api.*; +import com.bitwig.extension.controller.api.ControllerHost; +import com.bitwig.extension.controller.api.CursorTrack; +import com.bitwig.extension.controller.api.DocumentState; +import com.bitwig.extension.controller.api.SettableEnumValue; +import com.bitwig.extension.controller.api.TrackBank; +import com.bitwig.extension.controller.api.Transport; import com.bitwig.extensions.controllers.novation.commonsmk3.RgbState; import com.bitwig.extensions.controllers.novation.launchcontrolxlmk3.CcConstValues; import com.bitwig.extensions.controllers.novation.launchcontrolxlmk3.LaunchControlXlHwElements; @@ -14,124 +19,117 @@ @Component public class TransportHandler { - - private final BooleanValueObject shiftState; - private final CursorTrack cursorTrack; - private int trackItems; - private FocusMode focusMode = FocusMode.LAUNCHER; - private final Transport transport; - private final LaunchControlXlHwElements hwElements; - - public TransportHandler(final ControllerHost host, final LaunchControlXlHwElements hwElements, - final LaunchViewControl viewControl, final Transport transport) { - this.transport = transport; - this.shiftState = hwElements.getShiftState(); - this.cursorTrack = viewControl.getCursorTrack(); - this.hwElements = hwElements; - cursorTrack.position().markInterested(); - cursorTrack.channelIndex().markInterested(); - final TrackBank trackBank = viewControl.getTrackBank(); - trackBank.itemCount().addValueObserver(count -> this.trackItems = count); - final DocumentState documentState = host.getDocumentState(); - final SettableEnumValue focusMode = documentState.getEnumSetting( - "Focus", // - "Recording/Automation", - new String[]{FocusMode.LAUNCHER.getDescriptor(), FocusMode.ARRANGER.getDescriptor()}, - FocusMode.ARRANGER.getDescriptor()); - focusMode.addValueObserver(mode -> this.focusMode = FocusMode.toMode(mode)); - } - - public Transport getTransport() { - return transport; - } - - public void bindTransport(final Layer layer) { - final LaunchButton playButton = hwElements.getButton(CcConstValues.PLAY); - final LaunchButton recButton = hwElements.getButton(CcConstValues.RECORD); - transport.isPlaying().markInterested(); - transport.isClipLauncherOverdubEnabled().markInterested(); - transport.isArrangerRecordEnabled().markInterested(); - playButton.bindLight(layer, this::getPlayState); - playButton.bindPressed(layer, this::handlePlayPressed); - recButton.bindLight(layer, this::getRecordState); - recButton.bindPressed(layer, this::handleRecordPressed); - } - - public void bindTrackNavigation(final Layer layer) { - final LaunchButton trackLeftButton = hwElements.getButton(CcConstValues.TRACK_LEFT); - final LaunchButton trackRightButton = hwElements.getButton(CcConstValues.TRACK_RIGHT); - - trackLeftButton.bindLight(layer, () -> canNavLeft(cursorTrack) ? RgbState.WHITE : RgbState.OFF); - trackRightButton.bindLight(layer, () -> canNavRight(cursorTrack) ? RgbState.WHITE : RgbState.OFF); - - trackRightButton.bindRepeatHold(layer, () -> navRight(cursorTrack)); - trackLeftButton.bindRepeatHold(layer, () -> navLeft(cursorTrack)); - } - - private void handlePlayPressed() { - if (shiftState.get()) { - transport.continuePlayback(); - } else { - transport.play(); - } - } - - private void handleRecordPressed() { - if (focusMode == FocusMode.LAUNCHER) { - transport.isClipLauncherOverdubEnabled().toggle(); - } else { - transport.isArrangerRecordEnabled().toggle(); - } - } - - private RgbColorState getPlayState() { - return transport.isPlaying().get() ? RgbColorState.GREEN_FULL : RgbColorState.GREEN_DIM; - } - - private RgbColorState getRecordState() { - if (focusMode == FocusMode.LAUNCHER) { - return transport.isClipLauncherOverdubEnabled().get() - ? RgbColorState.RED_ORANGE_FULL - : RgbColorState.RED_ORANGE_DIM; - } - return transport.isArrangerRecordEnabled().get() ? RgbColorState.RED_FULL : RgbColorState.RED_DIM; - } - - - public boolean canNavLeft(final CursorTrack cursorTrack) { - if (shiftState.get()) { - return cursorTrack.channelIndex().get() > 0; - } - return cursorTrack.hasPrevious().get(); - } - - public void navRight(final CursorTrack cursorTrack) { - if (shiftState.get()) { - for (int i = 0; i < 8; i++) { - cursorTrack.selectNext(); - } - } else { - cursorTrack.selectNext(); - } - } - - public boolean canNavRight(final CursorTrack cursorTrack) { - if (shiftState.get()) { - return cursorTrack.channelIndex().get() + 8 < trackItems; - } - return cursorTrack.hasNext().get(); - } - - public void navLeft(final CursorTrack cursorTrack) { - if (shiftState.get()) { - if (canNavLeft(cursorTrack)) { - for (int i = 0; i < 8; i++) { - cursorTrack.selectPrevious(); - } - } - } else { - cursorTrack.selectPrevious(); - } - } - + + private final BooleanValueObject shiftState; + private final CursorTrack cursorTrack; + private FocusMode focusMode = FocusMode.LAUNCHER; + private final Transport transport; + private final LaunchControlXlHwElements hwElements; + private final LaunchViewControl viewControl; + + public TransportHandler(final ControllerHost host, final LaunchControlXlHwElements hwElements, + final LaunchViewControl viewControl, final Transport transport) { + this.transport = transport; + this.shiftState = hwElements.getShiftState(); + this.viewControl = viewControl; + this.cursorTrack = viewControl.getCursorTrack(); + this.hwElements = hwElements; + cursorTrack.position().markInterested(); + cursorTrack.channelIndex().markInterested(); + + final TrackBank trackBank = viewControl.getTrackBank(); + trackBank.itemCount().addValueObserver(count -> { + }); + final DocumentState documentState = host.getDocumentState(); + final SettableEnumValue focusMode = documentState.getEnumSetting( + "Focus", // + "Recording/Automation", + new String[] {FocusMode.LAUNCHER.getDescriptor(), FocusMode.ARRANGER.getDescriptor()}, + FocusMode.ARRANGER.getDescriptor()); + focusMode.addValueObserver(mode -> this.focusMode = FocusMode.toMode(mode)); + } + + public Transport getTransport() { + return transport; + } + + public void bindTransport(final Layer layer) { + final LaunchButton playButton = hwElements.getButton(CcConstValues.PLAY); + final LaunchButton recButton = hwElements.getButton(CcConstValues.RECORD); + transport.isPlaying().markInterested(); + transport.isClipLauncherOverdubEnabled().markInterested(); + transport.isArrangerRecordEnabled().markInterested(); + playButton.bindLight(layer, this::getPlayState); + playButton.bindPressed(layer, this::handlePlayPressed); + recButton.bindLight(layer, this::getRecordState); + recButton.bindPressed(layer, this::handleRecordPressed); + } + + public void bindTrackNavigation(final Layer layer) { + final LaunchButton trackLeftButton = hwElements.getButton(CcConstValues.TRACK_LEFT); + final LaunchButton trackRightButton = hwElements.getButton(CcConstValues.TRACK_RIGHT); + + trackLeftButton.bindLight(layer, () -> canNavLeft(cursorTrack) ? RgbState.WHITE : RgbState.OFF); + trackRightButton.bindLight(layer, () -> canNavRight(cursorTrack) ? RgbState.WHITE : RgbState.OFF); + + trackRightButton.bindRepeatHold(layer, this::navRight); + trackLeftButton.bindRepeatHold(layer, this::navLeft); + } + + private void handlePlayPressed() { + if (shiftState.get()) { + transport.continuePlayback(); + } else { + transport.play(); + } + } + + private void handleRecordPressed() { + if (focusMode == FocusMode.LAUNCHER) { + transport.isClipLauncherOverdubEnabled().toggle(); + } else { + transport.isArrangerRecordEnabled().toggle(); + } + } + + private RgbColorState getPlayState() { + return transport.isPlaying().get() ? RgbColorState.GREEN_FULL : RgbColorState.GREEN_DIM; + } + + private RgbColorState getRecordState() { + if (focusMode == FocusMode.LAUNCHER) { + return transport.isClipLauncherOverdubEnabled().get() + ? RgbColorState.RED_ORANGE_FULL + : RgbColorState.RED_ORANGE_DIM; + } + return transport.isArrangerRecordEnabled().get() ? RgbColorState.RED_FULL : RgbColorState.RED_DIM; + } + + public boolean canNavLeft(final CursorTrack cursorTrack) { + return cursorTrack.hasPrevious().get(); + } + + public boolean canNavRight(final CursorTrack cursorTrack) { + if (shiftState.get()) { + return viewControl.canScrollBy(8); + } + return cursorTrack.hasNext().get(); + } + + public void navRight() { + if (shiftState.get()) { + viewControl.navigateCursorBy(8); + } else { + viewControl.navigateCursorBy(1); + } + } + + public void navLeft() { + if (shiftState.get()) { + viewControl.navigateCursorBy(-8); + } else { + viewControl.navigateCursorBy(-1); + } + } + } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/LaunchkeyMk4Extension.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/LaunchkeyMk4Extension.java index e6e4f7f5..a4594ee2 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/LaunchkeyMk4Extension.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/LaunchkeyMk4Extension.java @@ -26,7 +26,6 @@ public class LaunchkeyMk4Extension extends ControllerExtension { private HardwareSurface surface; private Layer mainLayer; private Layer shiftLayer; - private final boolean hasFaders; private final boolean isMini; private MidiProcessor midiProcessor; private SessionLayer sessionLayer; @@ -43,9 +42,8 @@ public static void println(final String format, final Object... args) { } public LaunchkeyMk4Extension(final AbstractLaunchkeyMk4ExtensionDefinition definition, final ControllerHost host, - final boolean hasFaders, final boolean miniVersion) { + final boolean miniVersion) { super(definition, host); - this.hasFaders = hasFaders; this.isMini = miniVersion; } @@ -77,10 +75,8 @@ public void init() { } public void initGenerateModeHandling(final Context diContext) { - final SessionLayer sessionLayer = diContext.getService(SessionLayer.class); currentMainModeLayer = null; final DisplayControl display = diContext.getService(DisplayControl.class); - midiProcessor.addModeListener((type, id) -> this.handleModeChange(type, id, display)); } @@ -226,12 +222,11 @@ private void handleRestartPlay(final Transport transport) { private void setUpPreferences() { final DocumentState documentState = getHost().getDocumentState(); // THIS - final SettableEnumValue recordButtonAssignment = documentState.getEnumSetting("Record Button assignment", // + final SettableEnumValue recordButtonAssignment = documentState.getEnumSetting( + "Record Button assignment", // "Transport", new String[] {FocusMode.LAUNCHER.getDescriptor(), FocusMode.ARRANGER.getDescriptor()}, recordFocusMode.getDescriptor()); - recordButtonAssignment.addValueObserver(value -> { - recordFocusMode = FocusMode.toMode(value); - }); + recordButtonAssignment.addValueObserver(value -> recordFocusMode = FocusMode.toMode(value)); } @Override @@ -252,7 +247,7 @@ public void exit() { private void pause(final long timeMs) { try { - Thread.sleep(100); + Thread.sleep(timeMs); } catch (final InterruptedException e) { Thread.currentThread().interrupt(); diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/ViewControl.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/ViewControl.java index 167d530f..e90a125c 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/ViewControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/ViewControl.java @@ -22,7 +22,7 @@ @Component public class ViewControl { - + private static final int MAX_TRACKS = 64; private static final int MAX_SCENES = 2; private final TrackBank trackBank; @@ -36,7 +36,7 @@ public class ViewControl { private final CursorRemoteControlsPage primaryRemotes; private final CursorRemoteControlsPage trackRemotes; private final CursorRemoteControlsPage projectRemotes; - + private final BasicStringValue deviceDescriptor = new BasicStringValue(""); private final RemotePageName deviceRemotesPages; private final RemotePageName trackRemotesPages; @@ -54,16 +54,16 @@ public ViewControl(final ControllerHost host) { maxTrackBank = host.createTrackBank(MAX_TRACKS, 1, MAX_SCENES, false); maxTrackBank.sceneBank().scrollPosition().markInterested(); maxTrackBank.scrollPosition().markInterested(); - + cursorTrack = host.createCursorTrack(2, 16); - prepareTrack(-1, cursorTrack); + prepareTrack(cursorTrack); prepareSlots(cursorTrack); trackBank.followCursorTrack(cursorTrack); cursorTrack.exists().markInterested(); for (int i = 0; i < 8; i++) { final int index = i; final Track track = trackBank.getItemAt(i); - prepareTrack(i, track); + prepareTrack(track); track.addIsSelectedInMixerObserver(select -> { if (select) { this.selectedTrackIndex.set(index); @@ -72,45 +72,39 @@ public ViewControl(final ControllerHost host) { track.trackType().addValueObserver(type -> trackType[index] = type); track.canHoldNoteData().addValueObserver(canHoldNoteData -> this.canHoldNoteData[index] = canHoldNoteData); } - + sceneBank = trackBank.sceneBank(); sceneBank.scrollPosition().addValueObserver(scene -> maxTrackBank.sceneBank().scrollPosition().set(scene)); - + cursorClip = host.createLauncherCursorClip(16, 128); cursorClip.setStepSize(0.125); cursorClip.exists().markInterested(); arrangerClip = host.createArrangerCursorClip(16, 128); - + primaryDevice = cursorTrack.createCursorDevice("DrumDetection", "Pad Device", 2, CursorDeviceFollowMode.FIRST_INSTRUMENT); - cursorDevice = cursorTrack.createCursorDevice("device-control", "Device Control", 0, - CursorDeviceFollowMode.FOLLOW_SELECTION - ); + cursorDevice = cursorTrack.createCursorDevice( + "device-control", "Device Control", 0, + CursorDeviceFollowMode.FOLLOW_SELECTION); cursorDevice.isWindowOpen().markInterested(); - + primaryRemotes = cursorDevice.createCursorRemoteControlsPage(8); trackRemotes = cursorTrack.createCursorRemoteControlsPage(8); projectRemotes = rootTrack.createCursorRemoteControlsPage(8); deviceRemotesPages = new RemotePageName(primaryRemotes, cursorDevice.name()); trackRemotesPages = new RemotePageName(trackRemotes, new BasicStringValue("Track Remotes")); projectRemotesPages = new RemotePageName(projectRemotes, new BasicStringValue("Project Remotes")); - - cursorDevice.name().addValueObserver(deviceName -> { - deviceDescriptor.set(deviceName); - }); - + + cursorDevice.name().addValueObserver(deviceDescriptor::set); + sceneBank.canScrollBackwards().markInterested(); sceneBank.canScrollForwards().markInterested(); focusScene = sceneBank.getScene(0); focusScene.clipCount().markInterested(); } - - public IntValueObject getSelectedTrackIndex() { - return selectedTrackIndex; - } - private void prepareTrack(final int index, final Track track) { + private void prepareTrack(final Track track) { track.arm().markInterested(); track.exists().markInterested(); track.solo().markInterested(); @@ -118,7 +112,7 @@ private void prepareTrack(final int index, final Track track) { track.trackType().markInterested(); track.canHoldNoteData().markInterested(); } - + private void prepareSlots(final Track track) { final ClipLauncherSlotBank slots = track.clipLauncherSlotBank(); for (int i = 0; i < slots.getSizeOfBank(); i++) { @@ -136,67 +130,63 @@ public boolean canBeSelectedForSeq(final int index) { public RemotePageName getDeviceRemotesPages() { return deviceRemotesPages; } - + public RemotePageName getTrackRemotesPages() { return trackRemotesPages; } - + public RemotePageName getProjectRemotesPages() { return projectRemotesPages; } - + public TrackBank getTrackBank() { return trackBank; } - + public CursorTrack getCursorTrack() { return cursorTrack; } - + public Track getRootTrack() { return rootTrack; } - + public Clip getCursorClip() { return cursorClip; } - + public Clip getArrangerClip() { return arrangerClip; } - + public Scene getFocusScene() { return focusScene; } - + public SceneBank getSceneBank() { return sceneBank; } - + public PinnableCursorDevice getCursorDevice() { return cursorDevice; } - + public CursorRemoteControlsPage getPrimaryRemotes() { return primaryRemotes; } - + public CursorRemoteControlsPage getTrackRemotes() { return trackRemotes; } - + public CursorRemoteControlsPage getProjectRemotes() { return projectRemotes; } - + public PinnableCursorDevice getPrimaryDevice() { return primaryDevice; } - - public BasicStringValue getDeviceDescriptor() { - return deviceDescriptor; - } - + public static Optional filterSlot(final Track track, final Predicate check) { final ClipLauncherSlotBank slots = track.clipLauncherSlotBank(); for (int i = 0; i < slots.getSizeOfBank(); i++) { @@ -207,5 +197,5 @@ public static Optional filterSlot(final Track track, final Pre } return Optional.empty(); } - + } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMiniMk4ExtensionDefinition.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMiniMk4ExtensionDefinition.java index 5c8088e4..c35f6af7 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMiniMk4ExtensionDefinition.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMiniMk4ExtensionDefinition.java @@ -39,41 +39,44 @@ public void listAutoDetectionMidiPortNames(final AutoDetectionMidiPortNamesList if (platformType == PlatformType.WINDOWS) { for (final int variant : VARIANTS) { for (int i = 0; i < 4; i++) { - list.add(new String[] { - "MIDIIN2 (Launchkey Mini MK4 %d MIDI%s".formatted(variant, (i & 0x1) != 0 ? ")" : ""), - "Launchkey Mini MK4 %d MIDI".formatted(variant) - }, new String[] { - "MIDIOUT2 (Launchkey Mini MK4 %d MIDI%s".formatted(variant, (i & 0x2) != 0 ? ")" : ""), - "Launchkey Mini MK4 %d MIDI".formatted(variant) - }); + list.add( + new String[] { + "MIDIIN2 (Launchkey Mini MK4 %d MIDI%s".formatted(variant, (i & 0x1) != 0 ? ")" : ""), + "Launchkey Mini MK4 %d MIDI".formatted(variant) + }, new String[] { + "MIDIOUT2 (Launchkey Mini MK4 %d MIDI%s".formatted(variant, (i & 0x2) != 0 ? ")" : ""), + "Launchkey Mini MK4 %d MIDI".formatted(variant) + }); } } } else if (platformType == PlatformType.MAC) { for (final int variant : VARIANTS) { - list.add(new String[] { - "Launchkey Mini MK4 %d DAW Out".formatted(variant), - "Launchkey Mini MK4 %d MIDI Out".formatted(variant) - }, new String[] { - "Launchkey Mini MK4 %d DAW In".formatted(variant), - "Launchkey Mini MK4 %d MIDI In".formatted(variant) - }); + list.add( + new String[] { + "Launchkey Mini MK4 %d DAW Out".formatted(variant), + "Launchkey Mini MK4 %d MIDI Out".formatted(variant) + }, new String[] { + "Launchkey Mini MK4 %d DAW In".formatted(variant), + "Launchkey Mini MK4 %d MIDI In".formatted(variant) + }); } } else if (platformType == PlatformType.LINUX) { for (final int variant : VARIANTS) { - list.add(new String[] { - "Launchkey Mini MK4 %d Launchkey".formatted(variant), - "Launchkey Mini MK4 %d Launchkey #2".formatted(variant) - }, new String[] { - "Launchkey Mini MK4 %d Launchkey".formatted(variant), - "Launchkey Mini MK4 %d Launchkey #2".formatted(variant) - }); + list.add( + new String[] { + "Launchkey Mini MK4 %d Launchkey".formatted(variant), + "Launchkey Mini MK4 %d Launchkey #2".formatted(variant) + }, new String[] { + "Launchkey Mini MK4 %d Launchkey".formatted(variant), + "Launchkey Mini MK4 %d Launchkey #2".formatted(variant) + }); } } } @Override public LaunchkeyMk4Extension createInstance(final ControllerHost host) { - return new LaunchkeyMk4Extension(this, host, false, true); + return new LaunchkeyMk4Extension(this, host, true); } } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMk4ExtensionDefinition.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMk4ExtensionDefinition.java index 4a1b0636..6f70187e 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMk4ExtensionDefinition.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchkey_mk4/definition/LaunchkeyMk4ExtensionDefinition.java @@ -38,37 +38,42 @@ public void listAutoDetectionMidiPortNames(final AutoDetectionMidiPortNamesList if (platformType == PlatformType.WINDOWS) { for (final int variant : VARIANTS) { for (int i = 0; i < 4; i++) { - list.add(new String[] { - "MIDIIN2 (Launchkey MK4 %d MIDI%s".formatted(variant, (i & 0x1) != 0 ? ")" : ""), - "Launchkey MK4 %d MIDI".formatted(variant) - }, new String[] { - "MIDIOUT2 (Launchkey MK4 %d MIDI%s".formatted(variant, (i & 0x2) != 0 ? ")" : ""), - "Launchkey MK4 %d MIDI".formatted(variant) - }); + list.add( + new String[] { + "MIDIIN2 (Launchkey MK4 %d MIDI%s".formatted(variant, (i & 0x1) != 0 ? ")" : ""), + "Launchkey MK4 %d MIDI".formatted(variant) + }, new String[] { + "MIDIOUT2 (Launchkey MK4 %d MIDI%s".formatted(variant, (i & 0x2) != 0 ? ")" : ""), + "Launchkey MK4 %d MIDI".formatted(variant) + }); } } } else if (platformType == PlatformType.MAC) { for (final int variant : VARIANTS) { - list.add(new String[] { - "Launchkey MK4 %d DAW Out".formatted(variant), "Launchkey MK4 %d MIDI Out".formatted(variant) - }, new String[] { - "Launchkey MK4 %d DAW In".formatted(variant), "Launchkey MK4 %d MIDI In".formatted(variant) - }); + list.add( + new String[] { + "Launchkey MK4 %d DAW Out".formatted(variant), "Launchkey MK4 %d MIDI Out".formatted(variant) + }, new String[] { + "Launchkey MK4 %d DAW In".formatted(variant), "Launchkey MK4 %d MIDI In".formatted(variant) + }); } } else if (platformType == PlatformType.LINUX) { for (final int variant : VARIANTS) { - list.add(new String[] { - "Launchkey MK4 %d Launchkey".formatted(variant), "Launchkey MK4 %d Launchkey #2".formatted(variant) - }, new String[] { - "Launchkey MK4 %d Launchkey".formatted(variant), "Launchkey MK4 %d Launchkey #2".formatted(variant) - }); + list.add( + new String[] { + "Launchkey MK4 %d Launchkey".formatted(variant), + "Launchkey MK4 %d Launchkey #2".formatted(variant) + }, new String[] { + "Launchkey MK4 %d Launchkey".formatted(variant), + "Launchkey MK4 %d Launchkey #2".formatted(variant) + }); } } } @Override public LaunchkeyMk4Extension createInstance(final ControllerHost host) { - return new LaunchkeyMk4Extension(this, host, true, false); + return new LaunchkeyMk4Extension(this, host, false); } } diff --git a/src/main/resources/Documentation/Controllers/Expressive-e/Osmose.pdf b/src/main/resources/Documentation/Controllers/Expressive-e/Osmose.pdf index f0ef83ce..5c23c388 100644 Binary files a/src/main/resources/Documentation/Controllers/Expressive-e/Osmose.pdf and b/src/main/resources/Documentation/Controllers/Expressive-e/Osmose.pdf differ diff --git a/src/main/resources/Documentation/Controllers/Native Instruments/Kontrol S-Series/Kontrol S-Series Mk3.pdf b/src/main/resources/Documentation/Controllers/Native Instruments/Kontrol S-Series/Kontrol S-Series Mk3.pdf index e5349791..54cef336 100644 Binary files a/src/main/resources/Documentation/Controllers/Native Instruments/Kontrol S-Series/Kontrol S-Series Mk3.pdf and b/src/main/resources/Documentation/Controllers/Native Instruments/Kontrol S-Series/Kontrol S-Series Mk3.pdf differ