diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 5b781ec6..00000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/test/java=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 46235dc0..00000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 -org.eclipse.jdt.core.compiler.compliance=11 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.processAnnotations=disabled -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=11 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1..00000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/APC40MKIIControllerExtension.java b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/APC40MKIIControllerExtension.java index dc0e2f4f..706c140c 100644 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/APC40MKIIControllerExtension.java +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/APC40MKIIControllerExtension.java @@ -17,10 +17,10 @@ import com.bitwig.extension.controller.api.HardwareControlType; import com.bitwig.extension.controller.api.HardwareSlider; import com.bitwig.extension.controller.api.HardwareSurface; -import com.bitwig.extension.controller.api.HardwareTextDisplay; import com.bitwig.extension.controller.api.MasterTrack; import com.bitwig.extension.controller.api.MidiIn; import com.bitwig.extension.controller.api.MidiOut; +import com.bitwig.extension.controller.api.MultiStateHardwareLight; import com.bitwig.extension.controller.api.OnOffHardwareLight; import com.bitwig.extension.controller.api.PinnableCursorDevice; import com.bitwig.extension.controller.api.Preferences; @@ -41,7 +41,7 @@ import com.bitwig.extensions.framework.Layer; import com.bitwig.extensions.framework.Layers; -public class APC40MKIIControllerExtension extends ControllerExtension +class APC40MKIIControllerExtension extends ControllerExtension { private static final boolean ENABLE_DEBUG_LAYER = false; @@ -193,7 +193,7 @@ public void init() mIsMasterSelected = mTrackCursor.createEqualsValue(mMasterTrack); - PinnableCursorDevice channelStripDevice = + final PinnableCursorDevice channelStripDevice = mTrackCursor.createCursorDevice("channel-strip", "Channel Strip", 4, CursorDeviceFollowMode.LAST_DEVICE); channelStripDevice.exists().markInterested(); mChannelStripRemoteControls = channelStripDevice.createCursorRemoteControlsPage(8); @@ -515,7 +515,7 @@ private void createDebugLayer() { if (ENABLE_DEBUG_LAYER) { - Layer debugLayer = DebugUtilities.createDebugLayer(mLayers, mHardwareSurface); + final Layer debugLayer = DebugUtilities.createDebugLayer(mLayers, mHardwareSurface); debugLayer.activate(); } } @@ -547,11 +547,9 @@ private void createMainLayer() mMainLayer.bindToggle(mSoloButtons[x], track.solo()); mMainLayer.bindToggle(mArmButtons[x], track.arm()); mMainLayer.bindPressed(mABButtons[x], getHost().createAction(() -> { - final SettableEnumValue crossFadeMode = track.crossFadeMode(); - final int nextValue = (crossFadeToInt(crossFadeMode.get()) + 1) % 3; - crossFadeMode.set(intToCrossFade(nextValue)); + track.crossFadeMode().set(CrossFadeMode.forTrack(track).getNext().getEnumName()); }, () -> "Cycle through crossfade values")); - mMainLayer.bind(track.crossFadeMode(), mABLeds[x]); + mMainLayer.bindLightState(() -> CrossFadeMode.forTrack(track), mABLeds[x]); mMainLayer.bindPressed(mTrackSelectButtons[x], getHost().createAction(() -> mTrackCursor.selectChannel(track), () -> "Selects the track")); @@ -842,7 +840,7 @@ private void createTransportControls() mPlayButton.pressedAction().setActionMatcher(mMidiIn.createNoteOnActionMatcher(0, BT_PLAY)); mPlayButton.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_PLAY)); mPlayLed = mHardwareSurface.createOnOffHardwareLight("PlayLed"); - mPlayLed.onUpdateHardware(() -> sendLedUpdate(BT_PLAY, mPlayLed)); + mPlayLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_PLAY, isOn)); mPlayLed.setOnColor(Color.fromRGB(0, 1, 0)); mPlayButton.setBackgroundLight(mPlayLed); @@ -853,7 +851,7 @@ private void createTransportControls() mRecordButton.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_RECORD)); mRecordLed = mHardwareSurface.createOnOffHardwareLight("RecordLed"); mRecordLed.setOnColor(Color.fromRGB(1, 0, 0)); - mRecordLed.onUpdateHardware(() -> sendLedUpdate(BT_RECORD, mRecordLed)); + mRecordLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_RECORD, isOn)); mRecordButton.setBackgroundLight(mRecordLed); mSessionButton = mHardwareSurface.createHardwareButton("Session"); @@ -863,7 +861,7 @@ private void createTransportControls() mSessionButton.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_SESSION)); mSessionLed = mHardwareSurface.createOnOffHardwareLight("SessionLed"); mSessionLed.setOnColor(Color.fromRGB(1, 0, 0)); - mSessionLed.onUpdateHardware(() -> sendLedUpdate(BT_SESSION, mSessionLed)); + mSessionLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_SESSION, isOn)); mSessionButton.setBackgroundLight(mSessionLed); mMetronomeButton = mHardwareSurface.createHardwareButton("Metronome"); @@ -873,7 +871,7 @@ private void createTransportControls() mMetronomeButton.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_METRONOME)); mMetronomeLed = mHardwareSurface.createOnOffHardwareLight("MetronomeLed"); mMetronomeLed.setOnColor(Color.fromRGB255(255,165,0)); - mMetronomeLed.onUpdateHardware(() -> sendLedUpdate(BT_METRONOME, mMetronomeLed)); + mMetronomeLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_METRONOME, isOn)); mMetronomeButton.setBackgroundLight(mMetronomeLed); mTapTempoButton = mHardwareSurface.createHardwareButton("TapTempo"); @@ -882,14 +880,14 @@ private void createTransportControls() mTapTempoButton.pressedAction().setActionMatcher(mMidiIn.createNoteOnActionMatcher(0, BT_TAP_TEMPO)); mTapTempoButton.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_TAP_TEMPO)); - HardwareButton nudgePlusButton = mHardwareSurface.createHardwareButton("Nudge+"); + final HardwareButton nudgePlusButton = mHardwareSurface.createHardwareButton("Nudge+"); nudgePlusButton.setLabel("NUDGE +"); nudgePlusButton.setLabelPosition(RelativePosition.ABOVE); nudgePlusButton.pressedAction().setActionMatcher(mMidiIn.createNoteOnActionMatcher(0, BT_NUDGE_PLUS)); nudgePlusButton.releasedAction() .setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_NUDGE_PLUS)); - HardwareButton nudgeMinusButton = mHardwareSurface.createHardwareButton("Nudge-"); + final HardwareButton nudgeMinusButton = mHardwareSurface.createHardwareButton("Nudge-"); nudgeMinusButton.setLabel("NUDGE -"); nudgeMinusButton.setLabelPosition(RelativePosition.ABOVE); nudgeMinusButton.pressedAction() @@ -919,7 +917,7 @@ private void createTrackStopButtons() final int channel = x; final OnOffHardwareLight led = mHardwareSurface.createOnOffHardwareLight("TrackStopLed-" + x); led.setOnColor(Color.fromRGB255(255,165,0)); - led.onUpdateHardware(() -> sendLedUpdate(BT_TRACK_STOP, channel, led)); + led.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_TRACK_STOP, channel, isOn)); bt.setBackgroundLight(led); mTrackStopLeds[x] = led; } @@ -932,7 +930,7 @@ private void createTrackStopButtons() mMasterTrackStopLed = mHardwareSurface.createOnOffHardwareLight("MasterTrackStopLed"); mMasterTrackStopLed.setOnColor(Color.fromRGB255(255,165,0)); mMasterTrackStopButton.setBackgroundLight(mMasterTrackStopLed); - mMasterTrackStopLed.onUpdateHardware(() -> sendLedUpdate(BT_MASTER_STOP, mMasterTrackStopLed)); + mMasterTrackStopLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_MASTER_STOP, isOn)); } private void createTrackSelectButtons() @@ -950,7 +948,7 @@ private void createTrackSelectButtons() final int channel = x; final OnOffHardwareLight led = mHardwareSurface.createOnOffHardwareLight("TrackSelectLed-" + x); led.setOnColor(Color.fromRGB255(255,165,0)); - led.onUpdateHardware(() -> sendLedUpdate(BT_TRACK_SELECT, channel, led)); + led.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_TRACK_SELECT, channel, isOn)); bt.setBackgroundLight(led); mTrackSelectLeds[x] = led; } @@ -963,13 +961,13 @@ private void createTrackSelectButtons() mMasterTrackSelectLed = mHardwareSurface.createOnOffHardwareLight("MasterTrackSelectLed"); mMasterTrackSelectLed.setOnColor(Color.fromRGB255(255,165,0)); mMasterTrackSelectButton.setBackgroundLight(mMasterTrackSelectLed); - mMasterTrackSelectLed.onUpdateHardware(() -> sendLedUpdate(BT_MASTER_SELECT, mMasterTrackSelectLed)); + mMasterTrackSelectLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_MASTER_SELECT, isOn)); } private void createABButtons() { mABButtons = new HardwareButton[8]; - mABLeds = new HardwareTextDisplay[8]; + mABLeds = new MultiStateHardwareLight[8]; for (int x = 0; x < 8; ++x) { final HardwareButton bt = mHardwareSurface.createHardwareButton("AB-" + x); @@ -978,26 +976,18 @@ private void createABButtons() mABButtons[x] = bt; final int channel = x; - final HardwareTextDisplay led = mHardwareSurface.createHardwareTextDisplay("ABLed-" + x, 1); - led.onUpdateHardware(() -> sendLedUpdate(BT_TRACK_AB, channel, crossFadeToInt(led.line(0).text().currentValue()))); + final MultiStateHardwareLight led = mHardwareSurface.createMultiStateHardwareLight("ABLed-" + x); + led.setColorToStateFunction(CrossFadeMode::getBestModeForColor); + led.state().onUpdateHardware(state -> sendLedUpdate(BT_TRACK_AB, channel, (CrossFadeMode)state)); + bt.setBackgroundLight(led); mABLeds[x] = led; } } - private static Color getABLedColor(final int i) - { - return switch (i) - { - case 1 -> Color.fromRGB(1.0, 0.5, 0); - case 2 -> Color.fromRGB(0, 0, 1.0); - default -> Color.fromRGB(0, 0, 0); - }; - } - private void createArmButtons() { mArmButtons = new HardwareButton[8]; - OnOffHardwareLight[] armLeds = new OnOffHardwareLight[8]; + final OnOffHardwareLight[] armLeds = new OnOffHardwareLight[8]; for (int x = 0; x < 8; ++x) { final HardwareButton bt = mHardwareSurface.createHardwareButton("Arm-" + x); @@ -1010,7 +1000,7 @@ private void createArmButtons() final int channel = x; final OnOffHardwareLight led = mHardwareSurface.createOnOffHardwareLight("ArmLed-" + x); led.setOnColor(Color.fromRGB(1, 0, 0)); - led.onUpdateHardware(() -> sendLedUpdate(BT_TRACK_ARM, channel, led)); + led.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_TRACK_ARM, channel, isOn)); bt.setBackgroundLight(led); armLeds[x] = led; } @@ -1019,7 +1009,7 @@ private void createArmButtons() private void createSoloButtons() { mSoloButtons = new HardwareButton[8]; - OnOffHardwareLight[] soloLeds = new OnOffHardwareLight[8]; + final OnOffHardwareLight[] soloLeds = new OnOffHardwareLight[8]; for (int x = 0; x < 8; ++x) { final HardwareButton bt = mHardwareSurface.createHardwareButton("Solo-" + x); @@ -1032,7 +1022,7 @@ private void createSoloButtons() final int channel = x; final OnOffHardwareLight led = mHardwareSurface.createOnOffHardwareLight("SoloLed-" + x); led.setOnColor(Color.fromRGB(0, 0, 1)); - led.onUpdateHardware(() -> sendLedUpdate(BT_TRACK_SOLO, channel, led)); + led.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_TRACK_SOLO, channel, isOn)); bt.setBackgroundLight(led); soloLeds[x] = led; } @@ -1054,7 +1044,7 @@ private void createMuteButtons() final int channel = x; final OnOffHardwareLight led = mHardwareSurface.createOnOffHardwareLight("MuteLed-" + x); led.setOnColor(Color.fromRGB255(255,165,0)); - led.onUpdateHardware(() -> sendLedUpdate(BT_TRACK_MUTE, channel, led)); + led.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_TRACK_MUTE, channel, isOn)); bt.setBackgroundLight(led); mMuteLeds[x] = led; } @@ -1074,7 +1064,7 @@ private void createGridButtons() bt.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, note)); mGridButtons[y * 8 + x] = bt; - mGridLeds[x][y] = new RgbLed(bt, mHardwareSurface, MSG_NOTE_ON, BT_GRID0 + x + (4 - y) * 8); + mGridLeds[x][y] = new RgbLed(bt, mHardwareSurface, MSG_NOTE_ON, BT_GRID0 + x + (4 - y) * 8, mMidiOut); } } @@ -1087,7 +1077,7 @@ private void createGridButtons() bt.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_SCENE0 + y)); mSceneButtons[y] = bt; - mSceneLeds[y] = new RgbLed(bt, mHardwareSurface, MSG_NOTE_ON, BT_SCENE0 + y); + mSceneLeds[y] = new RgbLed(bt, mHardwareSurface, MSG_NOTE_ON, BT_SCENE0 + y, mMidiOut); } } @@ -1140,7 +1130,7 @@ private void createTopControls() mPanLed = mHardwareSurface.createOnOffHardwareLight("PanLed"); mPanLed.setOnColor(Color.fromRGB255(255,165,0)); mPanButton.setBackgroundLight(mPanLed); - mPanLed.onUpdateHardware(() -> sendLedUpdate(BT_PAN, mPanLed)); + mPanLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_PAN, isOn)); mSendsButton = mHardwareSurface.createHardwareButton("Sends"); mSendsButton.setLabel("SENDS"); @@ -1157,7 +1147,7 @@ private void createTopControls() mSendsLed = mHardwareSurface.createOnOffHardwareLight("SendsLed"); mSendsLed.setOnColor(Color.fromRGB255(255,165,0)); mSendsButton.setBackgroundLight(mSendsLed); - mSendsLed.onUpdateHardware(() -> sendLedUpdate(BT_SENDS, mSendsLed)); + mSendsLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_SENDS, isOn)); mUserButton = mHardwareSurface.createHardwareButton("User"); mUserButton.setLabel("USER"); @@ -1174,7 +1164,7 @@ private void createTopControls() mUserLed = mHardwareSurface.createOnOffHardwareLight("UserLed"); mUserLed.setOnColor(Color.fromRGB255(255,165,0)); mUserButton.setBackgroundLight(mUserLed); - mUserLed.onUpdateHardware(() -> sendLedUpdate(BT_USER, mUserLed)); + mUserLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_USER, isOn)); } private void createDeviceControls() @@ -1209,7 +1199,7 @@ private void createDeviceControls() mPrevDeviceLed = mHardwareSurface.createOnOffHardwareLight("PrevDeviceLed"); mPrevDeviceLed.setOnColor(Color.fromRGB255(255,165,0)); mPrevDeviceButton.setBackgroundLight(mPrevDeviceLed); - mPrevDeviceLed.onUpdateHardware(() -> sendLedUpdate(BT_PREV_DEVICE, mPrevDeviceLed)); + mPrevDeviceLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_PREV_DEVICE, isOn)); mNextDeviceButton = mHardwareSurface.createHardwareButton("NextDevice"); mNextDeviceButton.setLabel("DEVICE→"); @@ -1221,7 +1211,7 @@ private void createDeviceControls() mNextDeviceLed = mHardwareSurface.createOnOffHardwareLight("NextDeviceLed"); mNextDeviceLed.setOnColor(Color.fromRGB255(255,165,0)); mNextDeviceButton.setBackgroundLight(mNextDeviceLed); - mNextDeviceLed.onUpdateHardware(() -> sendLedUpdate(BT_NEXT_DEVICE, mNextDeviceLed)); + mNextDeviceLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_NEXT_DEVICE, isOn)); mPrevBankButton = mHardwareSurface.createHardwareButton("PrevBank"); mPrevBankButton.setLabel("←BANK"); @@ -1231,7 +1221,7 @@ private void createDeviceControls() mPrevBankLed = mHardwareSurface.createOnOffHardwareLight("PrevBankLed"); mPrevBankLed.setOnColor(Color.fromRGB255(255,165,0)); mPrevBankButton.setBackgroundLight(mPrevBankLed); - mPrevBankLed.onUpdateHardware(() -> sendLedUpdate(BT_PREV_BANK, mPrevBankLed)); + mPrevBankLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_PREV_BANK, isOn)); mNextBankButton = mHardwareSurface.createHardwareButton("NextBank"); mNextBankButton.setLabel("BANK→"); @@ -1241,7 +1231,7 @@ private void createDeviceControls() mNextBankLed = mHardwareSurface.createOnOffHardwareLight("NextBankLed"); mNextBankLed.setOnColor(Color.fromRGB255(255,165,0)); mNextBankButton.setBackgroundLight(mNextBankLed); - mNextBankLed.onUpdateHardware(() -> sendLedUpdate(BT_NEXT_BANK, mNextBankLed)); + mNextBankLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_NEXT_BANK, isOn)); mDeviceOnOffButton = mHardwareSurface.createHardwareButton("DeviceOnOff"); mDeviceOnOffButton.setLabel("DEV ON/OFF"); @@ -1253,7 +1243,7 @@ private void createDeviceControls() mDeviceOnOffLed = mHardwareSurface.createOnOffHardwareLight("DeviceOnOffLed"); mDeviceOnOffLed.setOnColor(Color.fromRGB255(255,165,0)); mDeviceOnOffButton.setBackgroundLight(mDeviceOnOffLed); - mDeviceOnOffLed.onUpdateHardware(() -> sendLedUpdate(BT_DEVICE_ONOFF, mDeviceOnOffLed)); + mDeviceOnOffLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_DEVICE_ONOFF, isOn)); mDeviceLockButton = mHardwareSurface.createHardwareButton("DeviceLock"); mDeviceLockButton.setLabel("DEV LOCK"); @@ -1265,7 +1255,7 @@ private void createDeviceControls() mDeviceLockLed = mHardwareSurface.createOnOffHardwareLight("DeviceLockLed"); mDeviceLockLed.setOnColor(Color.fromRGB255(255,165,0)); mDeviceLockButton.setBackgroundLight(mDeviceLockLed); - mDeviceLockLed.onUpdateHardware(() -> sendLedUpdate(BT_DEVICE_LOCK, mDeviceLockLed)); + mDeviceLockLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_DEVICE_LOCK, isOn)); mClipDeviceViewButton = mHardwareSurface.createHardwareButton("ClipDeviceView"); mClipDeviceViewButton.setLabel("CLIP/DEV VIEW"); @@ -1277,7 +1267,7 @@ private void createDeviceControls() mClipDeviceViewLed = mHardwareSurface.createOnOffHardwareLight("ClipDeviceViewLed"); mClipDeviceViewLed.setOnColor(Color.fromRGB255(255,165,0)); mClipDeviceViewButton.setBackgroundLight(mClipDeviceViewLed); - mClipDeviceViewLed.onUpdateHardware(() -> sendLedUpdate(BT_CLIP_DEVICE_VIEW, mClipDeviceViewLed)); + mClipDeviceViewLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_CLIP_DEVICE_VIEW, isOn)); mDetailViewButton = mHardwareSurface.createHardwareButton("DetailView"); mDetailViewButton.setLabel("DETAIL VIEW"); @@ -1289,7 +1279,7 @@ private void createDeviceControls() mDetailViewLed = mHardwareSurface.createOnOffHardwareLight("DetailViewLed"); mDetailViewLed.setOnColor(Color.fromRGB255(255,165,0)); mDetailViewButton.setBackgroundLight(mDetailViewLed); - mDetailViewLed.onUpdateHardware(() -> sendLedUpdate(BT_DETAIL_VIEW, mDetailViewLed)); + mDetailViewLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_DETAIL_VIEW, isOn)); mShiftButton = mHardwareSurface.createHardwareButton("Shift"); mShiftButton.setLabel("SHIFT"); @@ -1298,7 +1288,7 @@ private void createDeviceControls() mShiftButton.releasedAction().setActionMatcher(mMidiIn.createNoteOffActionMatcher(0, BT_SHIFT)); mShiftButton.isPressed().markInterested(); - HardwareButton bankButton = mHardwareSurface.createHardwareButton("Bank"); + final HardwareButton bankButton = mHardwareSurface.createHardwareButton("Bank"); bankButton.setLabel("BANK"); bankButton.setLabelPosition(RelativePosition.BELOW); bankButton.pressedAction().setActionMatcher(mMidiIn.createNoteOnActionMatcher(0, BT_BANK)); @@ -1319,7 +1309,7 @@ private void createDeviceControls() mBankLed = mHardwareSurface.createOnOffHardwareLight("BankLed"); mBankLed.setOnColor(Color.fromRGB255(255,165,0)); bankButton.setBackgroundLight(mBankLed); - mBankLed.onUpdateHardware(() -> sendLedUpdate(BT_BANK, mBankLed)); + mBankLed.isOn().onUpdateHardware(isOn -> sendLedUpdate(BT_BANK, isOn)); mLauncherUpButton = mHardwareSurface.createHardwareButton("LauncherUp"); mLauncherUpButton.setLabel("↑"); @@ -1388,14 +1378,19 @@ private void updateDeviceControlRing(final int knobIndex) getHost().requestFlush(); } - private void sendLedUpdate(final int note, final OnOffHardwareLight led) + private void sendLedUpdate(final int note, final boolean isOn) { - sendLedUpdate(note, 0, led); + sendLedUpdate(note, 0, isOn); } - private void sendLedUpdate(final int note, final int channel, final OnOffHardwareLight led) + private void sendLedUpdate(final int note, final int channel, final boolean isOn) { - mMidiOut.sendMidi((MSG_NOTE_ON << 4) | channel, note, led.isOn().currentValue() ? 1 : 0); + mMidiOut.sendMidi((MSG_NOTE_ON << 4) | channel, note, isOn ? 1 : 0); + } + + private void sendLedUpdate(final int note, final int channel, final CrossFadeMode lightState) + { + mMidiOut.sendMidi((MSG_NOTE_ON << 4) | channel, note, lightState != null ? lightState.getColorIndex() : CrossFadeMode.AB.getColorIndex()); } private void sendLedUpdate(final int note, final int channel, final int color) @@ -1428,25 +1423,6 @@ private void onSysexIn(final String sysex) mMidiOut.sendSysex("F0 47 7F 29 60 00 04 41 02 01 00 F7"); } - private String intToCrossFade(final int index) - { - return switch (index) - { - case 1 -> "A"; - case 2 -> "B"; - default -> "AB"; - }; - } - - private int crossFadeToInt(final String s) - { - if (s.equals("A")) - return 1; - if (s.equals("B")) - return 2; - return 0; - } - @Override public void exit() { @@ -1466,33 +1442,36 @@ private void paintScenes() for (int i = 0; i < 5; ++i) { final RgbLed rgbLed = mSceneLeds[i]; + + int colorValue = RGBLedState.COLOR_NONE, blinkColorValue = RGBLedState.COLOR_NONE, blinkType = RGBLedState.BLINK_NONE; + if (mSendsOn.isOn()) { final boolean isSelected = mSendIndex == i; - rgbLed.setColor(isSelected ? RGBLedState.COLOR_SELECTED : RGBLedState.COLOR_SELECTABLE); - rgbLed.setBlinkType(RGBLedState.BLINK_NONE); - rgbLed.setBlinkColor(RGBLedState.COLOR_NONE); + colorValue = isSelected ? RGBLedState.COLOR_SELECTED : RGBLedState.COLOR_SELECTABLE; + blinkType = RGBLedState.BLINK_NONE; + blinkColorValue = RGBLedState.COLOR_NONE; } else if (mUserOn.isOn()) { final boolean exists = i < mProjectRemoteControls.pageCount().get(); final boolean isSelected = exists && mProjectRemoteControls.selectedPageIndex().get() == i; - rgbLed.setColor(isSelected ? RGBLedState.COLOR_SELECTED : (exists ? RGBLedState.COLOR_SELECTABLE : RGBLedState.COLOR_NONE)); - rgbLed.setBlinkType(RGBLedState.BLINK_NONE); - rgbLed.setBlinkColor(RGBLedState.COLOR_NONE); + colorValue = isSelected ? RGBLedState.COLOR_SELECTED : (exists ? RGBLedState.COLOR_SELECTABLE : RGBLedState.COLOR_NONE); + blinkType = RGBLedState.BLINK_NONE; + blinkColorValue = RGBLedState.COLOR_NONE; } else { final Scene scene = mSceneBank.getScene(i); if (scene.exists().get()) - rgbLed.setColor(scene.color()); + colorValue = RGBLedState.getColorValueForColor(scene.color().get()); else - rgbLed.setColor(RGBLedState.COLOR_NONE); - rgbLed.setBlinkType(RGBLedState.BLINK_NONE); - rgbLed.setBlinkColor(RGBLedState.COLOR_NONE); + colorValue = (RGBLedState.COLOR_NONE); + blinkType = RGBLedState.BLINK_NONE; + blinkColorValue = RGBLedState.COLOR_NONE; } - rgbLed.paint(mMidiOut); + rgbLed.setState(new RGBLedState(colorValue, blinkColorValue, blinkType)); } } @@ -1502,15 +1481,16 @@ private void paintPads() { final Track track = mTrackBank.getItemAt(i); final ClipLauncherSlotBank clipLauncherSlotBank = track.clipLauncherSlotBank(); + for (int j = 0; j < 5; ++j) { final ClipLauncherSlot slot = clipLauncherSlotBank.getItemAt(j); final RgbLed rgbLed = mGridLeds[i][j]; + int colorValue = RGBLedState.COLOR_NONE, blinkColorValue = RGBLedState.COLOR_NONE, blinkType = RGBLedState.BLINK_NONE; + if (slot.exists().get() && slot.hasContent().get()) - rgbLed.setColor(slot.color().red(), slot.color().green(), slot.color().blue()); - else - rgbLed.setColor(RGBLedState.COLOR_NONE); + colorValue = RGBLedState.getColorValueForRGB(slot.color().red(), slot.color().green(), slot.color().blue()); /* * if (slot.isStopQueued().get()) { rgbLed.setBlinkType(RgbLed.BLINK_STOP_QUEUED); @@ -1519,33 +1499,33 @@ private void paintPads() if (slot.isRecordingQueued().get()) { - rgbLed.setBlinkType(RGBLedState.BLINK_RECORD_QUEUED); - rgbLed.setBlinkColor(RGBLedState.COLOR_RECORDING); + blinkType = RGBLedState.BLINK_RECORD_QUEUED; + blinkColorValue = RGBLedState.COLOR_RECORDING; } else if (slot.isPlaybackQueued().get()) { - rgbLed.setBlinkType(RGBLedState.BLINK_PLAY_QUEUED); - rgbLed.setBlinkColor(RGBLedState.COLOR_PLAYING_QUEUED); + blinkType = RGBLedState.BLINK_PLAY_QUEUED; + blinkColorValue = RGBLedState.COLOR_PLAYING_QUEUED; } else if (slot.isRecording().get()) { - rgbLed.setColor(RGBLedState.COLOR_NONE); - rgbLed.setBlinkType(RGBLedState.BLINK_ACTIVE); - rgbLed.setBlinkColor(RGBLedState.COLOR_RECORDING); + colorValue = RGBLedState.COLOR_NONE; + blinkType = RGBLedState.BLINK_ACTIVE; + blinkColorValue = RGBLedState.COLOR_RECORDING; } else if (slot.isPlaying().get()) { - rgbLed.setColor(RGBLedState.COLOR_NONE); - rgbLed.setBlinkType(RGBLedState.BLINK_ACTIVE); - rgbLed.setBlinkColor(RGBLedState.COLOR_PLAYING); + colorValue = RGBLedState.COLOR_NONE; + blinkType = RGBLedState.BLINK_ACTIVE; + blinkColorValue = RGBLedState.COLOR_PLAYING; } else /* stopped */ { - rgbLed.setBlinkType(RGBLedState.BLINK_NONE); - rgbLed.setBlinkColor(RGBLedState.COLOR_NONE); + blinkType = RGBLedState.BLINK_NONE; + blinkColorValue = RGBLedState.COLOR_NONE; } - rgbLed.paint(mMidiOut); + rgbLed.setState(new RGBLedState(colorValue, blinkColorValue, blinkType)); } } } @@ -1813,7 +1793,7 @@ void clear() private OnOffHardwareLight[] mMuteLeds; - private HardwareTextDisplay[] mABLeds; + private MultiStateHardwareLight[] mABLeds; private OnOffHardwareLight[] mTrackSelectLeds; diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/CrossFadeMode.java b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/CrossFadeMode.java new file mode 100644 index 00000000..422aae91 --- /dev/null +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/CrossFadeMode.java @@ -0,0 +1,117 @@ +package com.bitwig.extensions.controllers.akai.apc40_mkii; + +import com.bitwig.extension.api.Color; +import com.bitwig.extension.controller.api.HardwareLightVisualState; +import com.bitwig.extension.controller.api.InternalHardwareLightState; +import com.bitwig.extension.controller.api.Track; + +class CrossFadeMode extends InternalHardwareLightState +{ + public static final CrossFadeMode A = new CrossFadeMode("A", 0, 1); + + public static final CrossFadeMode B = new CrossFadeMode("B", 1, 2); + + public static final CrossFadeMode AB = new CrossFadeMode("AB", 2, 0); + + public static CrossFadeMode getBestModeForColor(final Color color) + { + if (color == null || color.getAlpha() == 0 + || color.getRed() == 0 && color.getGreen() == 0 && color.getBlue() == 0) + return AB; + + if (B_COLOR.equals(color)) + return B; + + return A; + } + + public static CrossFadeMode forEnumName(final String name) + { + if (name.equals(A.mEnumName)) + return A; + if (name.equals(B.mEnumName)) + return B; + return AB; + } + + public static CrossFadeMode forTrack(final Track track) + { + return forEnumName(track.crossFadeMode().get()); + } + + private static CrossFadeMode forIndex(final int index) + { + final CrossFadeMode mode = switch (index) + { + case 0 -> A; + case 1 -> B; + default -> AB; + }; + + assert mode.getIndex() == index; + + return mode; + } + + private CrossFadeMode(final String enumName, final int index, final int colorIndex) + { + mEnumName = enumName; + mIndex = index; + mColorIndex = colorIndex; + } + + public int getIndex() + { + return mIndex; + } + + /** The color value we need to send to the hardware */ + public int getColorIndex() + { + return mColorIndex; + } + + public CrossFadeMode getNext() + { + final int index = (mColorIndex + 1) % 3; + + return forIndex(index); + } + + public String getEnumName() + { + return mEnumName; + } + + @Override + public HardwareLightVisualState getVisualState() + { + if (this == AB) + return null; + + if (this == A) + return A_VISUAL_STATE; + + return B_VISUAL_STATE; + } + + @Override + public boolean equals(final Object obj) + { + return this == obj; + } + + private final String mEnumName; + + private final int mColorIndex, mIndex; + + private static final Color A_COLOR = Color.fromRGB(1, 0.64, 0); + + private static final Color B_COLOR = Color.fromRGB(0, 0, 1); + + private static final HardwareLightVisualState A_VISUAL_STATE = HardwareLightVisualState + .createForColor(A_COLOR); + + private static final HardwareLightVisualState B_VISUAL_STATE = HardwareLightVisualState + .createForColor(B_COLOR); +} diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/Led.java b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/Led.java deleted file mode 100644 index af17b6a8..00000000 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/Led.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.bitwig.extensions.controllers.akai.apc40_mkii; - -import com.bitwig.extension.controller.api.MidiOut; - -public class Led -{ - public void paint(final MidiOut midiOut, final int msg, final int channel, final int data1) - { - if (mValue == mDisplayedValue) - return; - - midiOut.sendMidi((msg << 4) | channel, data1, mValue); - mDisplayedValue = mValue; - } - - public void set(final int value) - { - mValue = value; - } - - private int mValue = 0; - - private int mDisplayedValue = -1; -} diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RGBLedState.java b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RGBLedState.java index cb992648..228672e0 100644 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RGBLedState.java +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RGBLedState.java @@ -47,6 +47,8 @@ class RGBLedState extends InternalHardwareLightState private static final Map COLOR_VALUE_TO_COLOR_MAP = new HashMap<>(); + public static final RGBLedState OFF_STATE = new RGBLedState(COLOR_NONE, COLOR_NONE, BLINK_NONE); + private static void registerColor(final int rgb, final int value) { COLOR_VALUE_TO_COLOR_MAP.put(value, @@ -110,11 +112,39 @@ public static int getColorValueForRGB(final int rgb) return 13; } + public static int getColorValueForRGB(final double red, final double green, final double blue) + { + final int r8 = (int)(red * 255); + final int g8 = (int)(green * 255); + final int b8 = (int)(blue * 255); + final int total = (r8 << 16) | (g8 << 8) | b8; + + return getColorValueForRGB(total); + } + + public static int getColorValueForColor(final Color color) + { + if (color == null || color.getAlpha() == 0) + return getColorValueForRGB(0); + + return getColorValueForRGB(color.getRed(), color.getGreen(), color.getBlue()); + } + public static Color getColorForColorValue(final int colorValue) { return COLOR_VALUE_TO_COLOR_MAP.get(colorValue); } + public static RGBLedState getBestStateForColor(final Color color) + { + if (color == null || color.getAlpha() == 0) + return OFF_STATE; + + final int colorValue = getColorValueForColor(color); + + return new RGBLedState(colorValue, COLOR_NONE, BLINK_NONE); + } + public RGBLedState(final int color, final int blinkColor, final int blinkType) { super(); diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RgbLed.java b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RgbLed.java index 71e779fb..59eb2baa 100644 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RgbLed.java +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apc40_mkii/RgbLed.java @@ -1,6 +1,5 @@ package com.bitwig.extensions.controllers.akai.apc40_mkii; -import com.bitwig.extension.controller.api.ColorValue; import com.bitwig.extension.controller.api.HardwareButton; import com.bitwig.extension.controller.api.HardwareSurface; import com.bitwig.extension.controller.api.MidiOut; @@ -14,86 +13,53 @@ protected RgbLed( final HardwareButton button, final HardwareSurface surface, final int message, - final int data1) + final int data1, + final MidiOut midiOut) { super(); mMessage = message; mData1 = data1; - MultiStateHardwareLight hardwareLight = surface.createMultiStateHardwareLight(button.getId() + "-light"); + final MultiStateHardwareLight hardwareLight = surface.createMultiStateHardwareLight(button.getId() + "-light"); hardwareLight.state().setValueSupplier(this::getState); + hardwareLight.setColorToStateFunction(RGBLedState::getBestStateForColor); + hardwareLight.state().onUpdateHardware(state -> sendLightState(midiOut, (RGBLedState)state)); button.setBackgroundLight(hardwareLight); } - public void paint(final MidiOut midiOut) + private void sendLightState(final MidiOut midiOut, RGBLedState state) { - if (mColor != mDisplayedColor || mBlinkColor != mDisplayedBlinkColor - || mBlinkType != mDisplayedBlinkType) + if (state == null) + state = RGBLedState.OFF_STATE; + + final var color = state.getColor(); + final var blinkColor = state.getBlinkColor(); + final var blinkType = state.getBlinkType(); + + midiOut.sendMidi(mMessage << 4, mData1, color); + + if (blinkType != RGBLedState.BLINK_NONE) { - midiOut.sendMidi(mMessage << 4, mData1, mColor); - - if (mBlinkType != RGBLedState.BLINK_NONE) - { - midiOut.sendMidi(mMessage << 4, mData1, mBlinkColor); - midiOut.sendMidi((mMessage << 4) | mBlinkType, mData1, mColor); - } - else - { - midiOut.sendMidi(mMessage << 4, mData1, mColor); - } - - mDisplayedColor = mColor; - mDisplayedBlinkColor = mBlinkColor; - mDisplayedBlinkType = mBlinkType; + midiOut.sendMidi(mMessage << 4, mData1, blinkColor); + midiOut.sendMidi((mMessage << 4) | blinkType, mData1, color); + } + else + { + midiOut.sendMidi(mMessage << 4, mData1, color); } } - public void setColor(final float red, final float green, final float blue) - { - final int r8 = (int)(red * 255); - final int g8 = (int)(green * 255); - final int b8 = (int)(blue * 255); - final int total = (r8 << 16) | (g8 << 8) | b8; - - mColor = RGBLedState.getColorValueForRGB(total); - } - - public void setColor(final int color) - { - mColor = color; - } - - public void setColor(final ColorValue color) - { - setColor(color.red(), color.green(), color.blue()); - } - - public void setBlinkType(final int blinkType) - { - mBlinkType = blinkType; - } - - public void setBlinkColor(final int blinkColor) + public RGBLedState getState() { - mBlinkColor = blinkColor; + return mState; } - public RGBLedState getState() + public void setState(final RGBLedState state) { - return new RGBLedState(mDisplayedColor, mDisplayedBlinkColor, mDisplayedBlinkType); + mState = state; } private final int mMessage, mData1; - private int mColor = RGBLedState.COLOR_NONE; - - private int mDisplayedColor = -1; - - private int mBlinkColor = RGBLedState.COLOR_NONE; - - private int mDisplayedBlinkColor = -1; - - private int mBlinkType = RGBLedState.BLINK_NONE; - - private int mDisplayedBlinkType = -1; + private RGBLedState mState; } diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/ApcButton.java b/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/ApcButton.java index 20e74066..429db677 100644 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/ApcButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/ApcButton.java @@ -1,15 +1,20 @@ package com.bitwig.extensions.controllers.akai.apcmk2.control; -import com.bitwig.extension.controller.api.*; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.bitwig.extension.controller.api.HardwareActionBindable; +import com.bitwig.extension.controller.api.HardwareButton; +import com.bitwig.extension.controller.api.HardwareSurface; +import com.bitwig.extension.controller.api.InternalHardwareLightState; +import com.bitwig.extension.controller.api.MidiIn; +import com.bitwig.extension.controller.api.MultiStateHardwareLight; import com.bitwig.extensions.controllers.akai.apcmk2.led.RgbLightState; import com.bitwig.extensions.controllers.akai.apcmk2.midi.MidiProcessor; import com.bitwig.extensions.framework.Layer; import com.bitwig.extensions.framework.time.TimeRepeatEvent; import com.bitwig.extensions.framework.time.TimedEvent; -import java.util.function.Function; -import java.util.function.Supplier; - public abstract class ApcButton { public static final int STD_REPEAT_DELAY = 400; public static final int STD_REPEAT_FREQUENCY = 50; @@ -21,7 +26,7 @@ public abstract class ApcButton { private long recordedDownTime; protected final int midiId; - protected ApcButton(final int channel, final int midiId, String name, HardwareSurface surface, + protected ApcButton(final int channel, final int midiId, final String name, final HardwareSurface surface, final MidiProcessor midiProcessor) { this.midiProcessor = midiProcessor; final MidiIn midiIn = midiProcessor.getMidiIn(); @@ -30,7 +35,9 @@ protected ApcButton(final int channel, final int midiId, String name, HardwareSu hwButton.pressedAction().setPressureActionMatcher(midiIn.createNoteOnVelocityValueMatcher(channel, midiId)); hwButton.releasedAction().setActionMatcher(midiIn.createNoteOffActionMatcher(channel, midiId)); light = surface.createMultiStateHardwareLight(name + "_LIGHT_" + midiId); + hwButton.setBackgroundLight(light); light.state().setValue(RgbLightState.OFF); + light.setColorToStateFunction(RgbLightState::forColor); hwButton.isPressed().markInterested(); } diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/RgbButton.java b/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/RgbButton.java index 6a33215c..98a5e326 100644 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/RgbButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/control/RgbButton.java @@ -8,7 +8,7 @@ public class RgbButton extends ApcButton { - protected RgbButton(final int channel, final int noteNr, String name, final HardwareSurface surface, + protected RgbButton(final int channel, final int noteNr, final String name, final HardwareSurface surface, final MidiProcessor midiProcessor) { super(channel, noteNr, name, surface, midiProcessor); light.state().setValue(RgbLightState.OFF); @@ -20,8 +20,7 @@ protected RgbButton(final int channel, final int noteNr, String name, final Hard } private void updateDrumState(final InternalHardwareLightState internalHardwareLightState) { - if (internalHardwareLightState instanceof RgbLightState) { - RgbLightState state = (RgbLightState) internalHardwareLightState; + if (internalHardwareLightState instanceof final RgbLightState state) { midiProcessor.sendMidi(Midi.NOTE_ON | 0x9, midiId, state.getColorIndex()); } else { midiProcessor.sendMidi(Midi.NOTE_ON, midiId, 0); @@ -31,7 +30,7 @@ private void updateDrumState(final InternalHardwareLightState internalHardwareLi private void updateState(final InternalHardwareLightState internalHardwareLightState) { if (internalHardwareLightState instanceof RgbLightState) { - RgbLightState state = (RgbLightState) internalHardwareLightState; + final RgbLightState state = (RgbLightState) internalHardwareLightState; midiProcessor.sendMidi(state.getMidiCode(), midiId, state.getColorIndex()); } else { midiProcessor.sendMidi(Midi.NOTE_ON, midiId, 0); diff --git a/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/led/RgbLightState.java b/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/led/RgbLightState.java index d298bb0c..9548413f 100644 --- a/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/led/RgbLightState.java +++ b/src/main/java/com/bitwig/extensions/controllers/akai/apcmk2/led/RgbLightState.java @@ -1,12 +1,13 @@ package com.bitwig.extensions.controllers.akai.apcmk2.led; +import java.util.HashMap; +import java.util.Map; + +import com.bitwig.extension.api.Color; import com.bitwig.extension.controller.api.HardwareLightVisualState; import com.bitwig.extension.controller.api.InternalHardwareLightState; import com.bitwig.extensions.framework.values.Midi; -import java.util.HashMap; -import java.util.Map; - public class RgbLightState extends InternalHardwareLightState { private static final Map STATE_MAP = new HashMap<>(); @@ -21,28 +22,38 @@ public class RgbLightState extends InternalHardwareLightState { private final int colorIndex; private final LedBehavior ledBehavior; - public static RgbLightState of(int colorIndex) { + public static RgbLightState of(final int colorIndex) { return STATE_MAP.computeIfAbsent(colorIndex | LedBehavior.FULL.getCode() << 8, - index -> new RgbLightState(colorIndex)); + index -> new RgbLightState(colorIndex)); } - public static RgbLightState of(int colorIndex, LedBehavior behavior) { + public static RgbLightState of(final int colorIndex, final LedBehavior behavior) { return STATE_MAP.computeIfAbsent(colorIndex | behavior.getCode() << 8, - index -> new RgbLightState(colorIndex, behavior)); + index -> new RgbLightState(colorIndex, behavior)); } - public RgbLightState behavior(LedBehavior behavior) { + public static RgbLightState forColor(final Color color) { + if (color == null || color.getAlpha() == 0 + || color.getRed() == 0 && color.getGreen() == 0 && color.getBlue() == 0) + return OFF; + + // TODO: Better color mapping here. + // This will be used for manual mapping feedback + return WHITE; + } + + public RgbLightState behavior(final LedBehavior behavior) { if (this.ledBehavior == behavior) { return this; } return of(this.colorIndex, behavior); } - private RgbLightState(int colorIndex) { + private RgbLightState(final int colorIndex) { this(colorIndex, LedBehavior.FULL); } - private RgbLightState(int colorIndex, LedBehavior ledBehavior) { + private RgbLightState(final int colorIndex, final LedBehavior ledBehavior) { this.colorIndex = colorIndex; this.ledBehavior = ledBehavior; } @@ -57,13 +68,17 @@ public int getMidiCode() { @Override public HardwareLightVisualState getVisualState() { - return null; + if (colorIndex == 0) + return null; + + // TODO: Better visual representation + return HardwareLightVisualState.createForColor(Color.fromRGB(1, 1, 1)); } @Override public boolean equals(final Object o) { if (o instanceof RgbLightState) { - RgbLightState other = (RgbLightState) o; + final RgbLightState other = (RgbLightState) o; return other.colorIndex == colorIndex && other.ledBehavior == ledBehavior; } return false; diff --git a/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/RgbButton.java b/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/RgbButton.java index d1d96fa5..a3d40805 100644 --- a/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/RgbButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/RgbButton.java @@ -1,15 +1,22 @@ package com.bitwig.extensions.controllers.arturia.keylab.essentialMk3; -import com.bitwig.extension.controller.api.*; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import com.bitwig.extension.controller.api.Action; +import com.bitwig.extension.controller.api.HardwareActionBindable; +import com.bitwig.extension.controller.api.HardwareButton; +import com.bitwig.extension.controller.api.HardwareSurface; +import com.bitwig.extension.controller.api.InternalHardwareLightState; +import com.bitwig.extension.controller.api.MidiIn; +import com.bitwig.extension.controller.api.MultiStateHardwareLight; +import com.bitwig.extension.controller.api.SettableBooleanValue; import com.bitwig.extensions.controllers.arturia.keylab.essentialMk3.color.RgbLightState; import com.bitwig.extensions.controllers.arturia.keylab.essentialMk3.components.SysExHandler; import com.bitwig.extensions.framework.Layer; import com.bitwig.extensions.framework.time.TimeRepeatEvent; import com.bitwig.extensions.framework.time.TimedEvent; -import java.util.function.Consumer; -import java.util.function.Supplier; - public class RgbButton { private final byte[] rgbCommand = {(byte) 0xF0, 0x00, 0x20, 0x6B, 0x7F, 0x42, 0x04, // 0x01, // 7 - Patch Id @@ -51,6 +58,7 @@ public RgbButton(final String name, final int padId, final Type type, final int } hwButton.isPressed().markInterested(); light = surface.createMultiStateHardwareLight(name + "_LIGHT_" + "_" + value); + light.setColorToStateFunction(RgbLightState::forColor); hwButton.setBackgroundLight(light); light.state().onUpdateHardware(this::updateState); // if (bankId.getIndex() == -1) { // Individual updates handled @@ -73,8 +81,8 @@ public MultiStateHardwareLight getLight() { } private void updateState(final InternalHardwareLightState state) { - if (state instanceof RgbLightState) { - ((RgbLightState) state).apply(rgbCommand); + if (state instanceof final RgbLightState ligtState) { + ligtState.apply(rgbCommand); sysExHandler.sendSysex(rgbCommand); } else { setRgbOff(); diff --git a/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/color/RgbLightState.java b/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/color/RgbLightState.java index 5d54a58f..e1805c51 100644 --- a/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/color/RgbLightState.java +++ b/src/main/java/com/bitwig/extensions/controllers/arturia/keylab/essentialMk3/color/RgbLightState.java @@ -1,16 +1,12 @@ package com.bitwig.extensions.controllers.arturia.keylab.essentialMk3.color; +import java.util.Arrays; + import com.bitwig.extension.api.Color; import com.bitwig.extension.controller.api.HardwareLightVisualState; import com.bitwig.extension.controller.api.InternalHardwareLightState; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - public class RgbLightState extends InternalHardwareLightState { - private static final Map indexLookup = new HashMap<>(); - private static final int DIM_VAL = 0x20; private static final int MAX_VAL = 0x7F; @@ -37,6 +33,18 @@ public class RgbLightState extends InternalHardwareLightState { private final HardwareLightVisualState visualState; private final BlinkState state; + public static RgbLightState forColor(final Color color) + { + if (color == null || color.getAlpha() == 0) + return OFF; + + final int red = (int)(color.getRed() * MAX_VAL); + final int green = (int)(color.getGreen() * MAX_VAL); + final int blue = (int)(color.getBlue() * MAX_VAL); + + return new RgbLightState(red, green, blue); + } + RgbLightState(final int red, final int green, final int blue, final BlinkState state) { rgb = saturate(red, green, blue, SAT_AMOUNT); this.state = state; diff --git a/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/ClipLaunchingLayer.java b/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/ClipLaunchingLayer.java index a8605e80..aded9016 100644 --- a/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/ClipLaunchingLayer.java +++ b/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/ClipLaunchingLayer.java @@ -1,13 +1,13 @@ package com.bitwig.extensions.controllers.arturia.minilab3; +import java.util.Arrays; + import com.bitwig.extension.controller.api.ClipLauncherSlot; import com.bitwig.extension.controller.api.MultiStateHardwareLight; import com.bitwig.extension.controller.api.Track; import com.bitwig.extension.controller.api.TrackBank; import com.bitwig.extensions.framework.Layer; -import java.util.Arrays; - public class ClipLaunchingLayer extends Layer { private final RgbLightState[] sceneSlotColors = new RgbLightState[8]; @@ -17,8 +17,6 @@ public class ClipLaunchingLayer extends Layer { private final MiniLab3Extension driver; private int blinkState; private long clipsStopTiming = 800; - private final byte[] colorBuffer = new byte[24]; - private final byte[] currentBuffer = new byte[24]; public ClipLaunchingLayer(final MiniLab3Extension driver) { super(driver.getLayers(), "CLIP LAUNCHER"); diff --git a/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/MiniLab3Extension.java b/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/MiniLab3Extension.java index ac41b8f2..e110fa87 100644 --- a/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/MiniLab3Extension.java +++ b/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/MiniLab3Extension.java @@ -1,22 +1,52 @@ package com.bitwig.extensions.controllers.arturia.minilab3; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.function.IntConsumer; + import com.bitwig.extension.api.util.midi.ShortMidiMessage; import com.bitwig.extension.callback.ShortMidiMessageReceivedCallback; import com.bitwig.extension.controller.ControllerExtension; -import com.bitwig.extension.controller.api.*; +import com.bitwig.extension.controller.api.AbsoluteHardwareControl; +import com.bitwig.extension.controller.api.AbsoluteHardwareKnob; +import com.bitwig.extension.controller.api.BooleanValue; +import com.bitwig.extension.controller.api.ControllerHost; +import com.bitwig.extension.controller.api.CursorDeviceFollowMode; +import com.bitwig.extension.controller.api.CursorRemoteControlsPage; +import com.bitwig.extension.controller.api.CursorTrack; +import com.bitwig.extension.controller.api.Device; +import com.bitwig.extension.controller.api.DeviceBank; +import com.bitwig.extension.controller.api.DeviceMatcher; +import com.bitwig.extension.controller.api.DocumentState; +import com.bitwig.extension.controller.api.HardwareActionBindable; +import com.bitwig.extension.controller.api.HardwareButton; +import com.bitwig.extension.controller.api.HardwareSlider; +import com.bitwig.extension.controller.api.HardwareSurface; +import com.bitwig.extension.controller.api.InternalHardwareLightState; +import com.bitwig.extension.controller.api.MidiIn; +import com.bitwig.extension.controller.api.MidiOut; +import com.bitwig.extension.controller.api.NoteInput; +import com.bitwig.extension.controller.api.Parameter; +import com.bitwig.extension.controller.api.PinnableCursorDevice; +import com.bitwig.extension.controller.api.Preferences; +import com.bitwig.extension.controller.api.RelativeHardwareKnob; +import com.bitwig.extension.controller.api.RelativeHardwareValueMatcher; +import com.bitwig.extension.controller.api.RemoteControl; +import com.bitwig.extension.controller.api.Scene; +import com.bitwig.extension.controller.api.SettableEnumValue; +import com.bitwig.extension.controller.api.SettableRangedValue; +import com.bitwig.extension.controller.api.StringValue; +import com.bitwig.extension.controller.api.TrackBank; +import com.bitwig.extension.controller.api.Transport; import com.bitwig.extensions.framework.Layer; import com.bitwig.extensions.framework.Layers; import com.bitwig.extensions.framework.values.BasicStringValue; import com.bitwig.extensions.framework.values.BooleanValueObject; import com.bitwig.extensions.framework.values.ValueObject; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.function.IntConsumer; - public class MiniLab3Extension extends ControllerExtension { public static final int NUM_PADS_TRACK = 8; @@ -68,7 +98,7 @@ public class MiniLab3Extension extends ControllerExtension { private Transport transport; private PinnableCursorDevice primaryDevice; private FocusMode recordFocusMode = FocusMode.ARRANGER; - private EncoderStateMaschine encoderStateMaschine = new EncoderStateMaschine(); + private final EncoderStateMaschine encoderStateMaschine = new EncoderStateMaschine(); protected MiniLab3Extension(final MiniLab3ExtensionDefinition definition, final ControllerHost host) { super(definition, host); @@ -280,7 +310,7 @@ private void setUpFollowArturiaDevice() { private void setUpPreferences() { - DocumentState documentState = getHost().getDocumentState(); // THIS + final DocumentState documentState = getHost().getDocumentState(); // THIS final SettableEnumValue recordButtonAssignment = documentState.getEnumSetting("Record Button assignment", // "Transport", new String[]{FocusMode.LAUNCHER.getDescriptor(), FocusMode.ARRANGER.getDescriptor()}, recordFocusMode.getDescriptor()); @@ -288,7 +318,7 @@ private void setUpPreferences() { recordFocusMode = FocusMode.toMode(value); updateTrackInfo(); }); - Preferences preferences = getHost().getPreferences(); + final Preferences preferences = getHost().getPreferences(); final SettableEnumValue clipStopTiming = preferences.getEnumSetting("Long press to stop clip", // "Clip", new String[]{"Fast", "Medium", "Standard"}, "Medium"); clipStopTiming.addValueObserver(clipLaunchingLayer::setClipStopTiming); @@ -582,7 +612,7 @@ private void mainEncoderShiftAction(final int dir) { } } - private void navigateScenesOrPads(int dir) { + private void navigateScenesOrPads(final int dir) { if (padBank.get() == PadBank.BANK_A) { oled.enableValues(DisplayMode.SCENE); oled.sendTextInfo(DisplayMode.SCENE, cursorTrack.name().get(), sceneTrackItem.name().get(), true); @@ -660,8 +690,8 @@ public TrackBank getViewTrackBank() { } public void updateBankState(final InternalHardwareLightState state) { - if (state instanceof RgbBankLightState) { - sysExHandler.sendBankState((RgbBankLightState) state); + if (state instanceof final RgbBankLightState lightState) { + sysExHandler.sendBankState(lightState); } } @@ -713,7 +743,7 @@ public void flush() { /** * Make sure no scene is launched upon release. */ - public void notifyTurn(boolean shift) { + public void notifyTurn(final boolean shift) { encoderStateMaschine.notifyTurn(shift); } diff --git a/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/RgbBankLightState.java b/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/RgbBankLightState.java index 7f3ea01b..f941eec1 100644 --- a/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/RgbBankLightState.java +++ b/src/main/java/com/bitwig/extensions/controllers/arturia/minilab3/RgbBankLightState.java @@ -71,8 +71,7 @@ public HardwareLightVisualState getVisualState() { @Override public boolean equals(final Object obj) { - if (obj instanceof RgbBankLightState) { - final RgbBankLightState other = (RgbBankLightState) obj; + if (obj instanceof final RgbBankLightState other) { return other.bank == bank && Arrays.equals(other.colors, colors); } return false; diff --git a/src/main/java/com/bitwig/extensions/controllers/icon/VCast.java b/src/main/java/com/bitwig/extensions/controllers/icon/VCast.java index 38e8b68b..8e1d3a3d 100644 --- a/src/main/java/com/bitwig/extensions/controllers/icon/VCast.java +++ b/src/main/java/com/bitwig/extensions/controllers/icon/VCast.java @@ -1,7 +1,5 @@ package com.bitwig.extensions.controllers.icon; -import java.util.Arrays; -import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -19,7 +17,6 @@ import com.bitwig.extension.controller.api.HardwareLightVisualState; import com.bitwig.extension.controller.api.HardwareSlider; import com.bitwig.extension.controller.api.HardwareSurface; -import com.bitwig.extension.controller.api.HardwareTextDisplay; import com.bitwig.extension.controller.api.InternalHardwareLightState; import com.bitwig.extension.controller.api.MidiIn; import com.bitwig.extension.controller.api.MidiOut; @@ -176,13 +173,8 @@ private void initVuMeter() mVuMeterLight = mHardwareSurface.createMultiStateHardwareLight("vuMeter"); mVuMeterLight.state().setValue(new VuMeterState()); mVuMeterLight.state().onUpdateHardware((state) -> { - if (!(state instanceof VuMeterState)) - { - return; - } - - final VuMeterState s = (VuMeterState) state; - mMidiOut.sendMidi(0xD0, 0x30 + s.value(), 0x00); + if (state instanceof final VuMeterState s) + mMidiOut.sendMidi(0xD0, 0x30 + s.value(), 0x00); }); } diff --git a/src/main/java/com/bitwig/extensions/controllers/mackie/section/MixControl.java b/src/main/java/com/bitwig/extensions/controllers/mackie/section/MixControl.java index 98795521..53eff973 100644 --- a/src/main/java/com/bitwig/extensions/controllers/mackie/section/MixControl.java +++ b/src/main/java/com/bitwig/extensions/controllers/mackie/section/MixControl.java @@ -1,12 +1,30 @@ package com.bitwig.extensions.controllers.mackie.section; -import com.bitwig.extension.controller.api.*; +import com.bitwig.extension.controller.api.Channel; +import com.bitwig.extension.controller.api.CursorDeviceLayer; +import com.bitwig.extension.controller.api.CursorTrack; +import com.bitwig.extension.controller.api.Device; +import com.bitwig.extension.controller.api.DrumPad; +import com.bitwig.extension.controller.api.DrumPadBank; +import com.bitwig.extension.controller.api.InsertionPoint; +import com.bitwig.extension.controller.api.MidiIn; +import com.bitwig.extension.controller.api.MidiOut; +import com.bitwig.extension.controller.api.MultiStateHardwareLight; +import com.bitwig.extension.controller.api.NoteInput; +import com.bitwig.extension.controller.api.PinnableCursorDevice; +import com.bitwig.extension.controller.api.SendBank; +import com.bitwig.extension.controller.api.TrackBank; import com.bitwig.extensions.controllers.mackie.ButtonViewState; import com.bitwig.extensions.controllers.mackie.MackieMcuProExtension; import com.bitwig.extensions.controllers.mackie.MixerMode; import com.bitwig.extensions.controllers.mackie.VPotMode; -import com.bitwig.extensions.controllers.mackie.configurations.*; +import com.bitwig.extensions.controllers.mackie.configurations.BrowserConfiguration; import com.bitwig.extensions.controllers.mackie.configurations.BrowserConfiguration.Type; +import com.bitwig.extensions.controllers.mackie.configurations.DeviceMenuConfiguration; +import com.bitwig.extensions.controllers.mackie.configurations.GlovalViewLayerConfiguration; +import com.bitwig.extensions.controllers.mackie.configurations.LayerConfiguration; +import com.bitwig.extensions.controllers.mackie.configurations.MixerLayerConfiguration; +import com.bitwig.extensions.controllers.mackie.configurations.TrackLayerConfiguration; import com.bitwig.extensions.controllers.mackie.devices.CursorDeviceControl; import com.bitwig.extensions.controllers.mackie.devices.DeviceManager; import com.bitwig.extensions.controllers.mackie.devices.DeviceTypeBank; @@ -15,7 +33,11 @@ import com.bitwig.extensions.controllers.mackie.display.LcdDisplay; import com.bitwig.extensions.controllers.mackie.display.RingDisplayType; import com.bitwig.extensions.controllers.mackie.display.VuMode; -import com.bitwig.extensions.controllers.mackie.layer.*; +import com.bitwig.extensions.controllers.mackie.layer.ClipLaunchButtonLayer; +import com.bitwig.extensions.controllers.mackie.layer.DrumMixerLayerGroup; +import com.bitwig.extensions.controllers.mackie.layer.HelperInfo; +import com.bitwig.extensions.controllers.mackie.layer.MixerLayerGroup; +import com.bitwig.extensions.controllers.mackie.layer.NotePlayingButtonLayer; import com.bitwig.extensions.controllers.mackie.seqencer.NoteSequenceLayer; import com.bitwig.extensions.controllers.mackie.value.BooleanValueObject; import com.bitwig.extensions.controllers.mackie.value.ModifierValueObject; @@ -71,8 +93,8 @@ public MixControl(final MackieMcuProExtension driver, final MidiIn midiIn, final if (hasTrackColoring) { backgroundColoring.state().onUpdateHardware(state -> { - if (state instanceof TrackColor) { - ((TrackColor) state).send(midiOut); + if (state instanceof final TrackColor trackColor) { + trackColor.send(midiOut); } }); } diff --git a/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/RgbColor.java b/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/RgbColor.java index 4400cb4a..98f2e9ca 100644 --- a/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/RgbColor.java +++ b/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/RgbColor.java @@ -1,10 +1,10 @@ package com.bitwig.extensions.controllers.maudio.oxygenpro; +import java.awt.Color; + import com.bitwig.extension.controller.api.HardwareLightVisualState; import com.bitwig.extension.controller.api.InternalHardwareLightState; -import java.awt.*; - public class RgbColor extends InternalHardwareLightState { private static final int BLINK = 64; @@ -24,15 +24,15 @@ public class RgbColor extends InternalHardwareLightState { public static final RgbColor MAGENTA = new RgbColor(51); public static final RgbColor ROSE = new RgbColor(35); - private int stateIndex; - private RgbColor blink; + private final int stateIndex; + private final RgbColor blink; - private RgbColor(int stateIndex) { + private RgbColor(final int stateIndex) { this.stateIndex = stateIndex; this.blink = new RgbColor(this); } - private RgbColor(RgbColor base) { + private RgbColor(final RgbColor base) { this.stateIndex = base.stateIndex + BLINK; this.blink = this; } @@ -47,32 +47,35 @@ public int getStateIndex() { @Override public HardwareLightVisualState getVisualState() { - return null; + if (stateIndex == 0) + return null; + + return HardwareLightVisualState.createForColor(com.bitwig.extension.api.Color.fromRGB(1, 1, 1)); } @Override - public boolean equals(Object obj) { + public boolean equals(final Object obj) { if (obj instanceof RgbColor) { - RgbColor other = (RgbColor) obj; + final RgbColor other = (RgbColor) obj; return other.stateIndex == stateIndex; } return false; } - public static RgbColor toColor(double red, double green, double blue) { + public static RgbColor toColor(final double red, final double green, final double blue) { final int rv = (int) Math.floor(red * 255); final int gv = (int) Math.floor(green * 255); final int bv = (int) Math.floor(blue * 255); if (rv == 0 && gv == 0 && bv == 0) { return RgbColor.OFF; } - Hsb hsb = rgbToHsb(rv, gv, bv); - //DebugOutOxy.println("x Color %d %d %d %s", rv, gv, bv, hsb); + final Hsb hsb = rgbToHsb(rv, gv, bv); + // DebugOutOxy.println("x Color %d %d %d %s", rv, gv, bv, hsb); return toColor(hsb); } - private static RgbColor toColor(Hsb hsb) { + private static RgbColor toColor(final Hsb hsb) { if (hsb.sat < 4) { return RgbColor.WHITE; } @@ -109,11 +112,11 @@ private static RgbColor toColor(Hsb hsb) { } private static Hsb rgbToHsb(final int rv, final int gv, final int bv) { - float[] hsbValues = new float[3]; + final float[] hsbValues = new float[3]; Color.RGBtoHSB(rv, gv, bv, hsbValues); - int hr = Math.round(hsbValues[0] * 15) + 1; - int hg = Math.round(hsbValues[1] * 15); - int hb = Math.round(hsbValues[2] * 15); + final int hr = Math.round(hsbValues[0] * 15) + 1; + final int hg = Math.round(hsbValues[1] * 15); + final int hb = Math.round(hsbValues[2] * 15); return new Hsb(hr, hg, hb); } diff --git a/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/control/PadButton.java b/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/control/PadButton.java index c2ecf796..86a86b68 100644 --- a/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/control/PadButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/maudio/oxygenpro/control/PadButton.java @@ -1,5 +1,7 @@ package com.bitwig.extensions.controllers.maudio.oxygenpro.control; +import java.util.function.Supplier; + import com.bitwig.extension.controller.api.HardwareSurface; import com.bitwig.extension.controller.api.InternalHardwareLightState; import com.bitwig.extension.controller.api.MidiIn; @@ -10,33 +12,33 @@ import com.bitwig.extensions.framework.Layer; import com.bitwig.extensions.framework.values.Midi; -import java.util.function.Supplier; - public class PadButton extends OxygenButton { private final MultiStateHardwareLight light; - public PadButton(final int midiId, String name, HardwareSurface surface, MidiProcessor midiProcessor) { + public PadButton(final int midiId, final String name, final HardwareSurface surface, final MidiProcessor midiProcessor) { super(midiId, midiProcessor); - MidiIn midiIn = midiProcessor.getMidiIn(); + final MidiIn midiIn = midiProcessor.getMidiIn(); hwButton = surface.createHardwareButton(name + "_" + midiId); hwButton.pressedAction().setPressureActionMatcher(midiIn.createNoteOnVelocityValueMatcher(0, midiId)); hwButton.releasedAction().setActionMatcher(midiIn.createNoteOffActionMatcher(0, midiId)); hwButton.isPressed().markInterested(); light = surface.createMultiStateHardwareLight(name + "_LIGHT_" + midiId); light.state().setValue(RgbLightState.OFF); + light.setColorToStateFunction(RgbLightState::forColor); hwButton.isPressed().markInterested(); light.state().onUpdateHardware(this::updateState); + hwButton.setBackgroundLight(light); } - private void updateState(InternalHardwareLightState state) { - if (state instanceof RgbColor rgbState) { + private void updateState(final InternalHardwareLightState state) { + if (state instanceof final RgbColor rgbState) { midiProcessor.sendMidi(Midi.NOTE_ON, midiId, rgbState.getStateIndex()); } } - public void bindLight(Layer layer, final Supplier supplier) { + public void bindLight(final Layer layer, final Supplier supplier) { layer.bindLightState(supplier, this.light); } diff --git a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/maschinemikro/buttons/RgbButton.java b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/maschinemikro/buttons/RgbButton.java index 51429d6d..78856a2c 100644 --- a/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/maschinemikro/buttons/RgbButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/nativeinstruments/maschinemikro/buttons/RgbButton.java @@ -1,5 +1,7 @@ package com.bitwig.extensions.controllers.nativeinstruments.maschinemikro.buttons; +import java.util.function.Supplier; + import com.bitwig.extension.controller.api.HardwareSurface; import com.bitwig.extension.controller.api.InternalHardwareLightState; import com.bitwig.extension.controller.api.MidiIn; @@ -9,14 +11,12 @@ import com.bitwig.extensions.controllers.nativeinstruments.maschinemikro.RgbColor; import com.bitwig.extensions.framework.Layer; -import java.util.function.Supplier; - public class RgbButton extends GateButton { private final MultiStateHardwareLight light; - public RgbButton(final int midiId, String name, HardwareSurface surface, MidiProcessor midiProcessor) { + public RgbButton(final int midiId, final String name, final HardwareSurface surface, final MidiProcessor midiProcessor) { super(midiId, midiProcessor); - MidiIn midiIn = midiProcessor.getMidiIn(); + final MidiIn midiIn = midiProcessor.getMidiIn(); hwButton = surface.createHardwareButton(name + "_" + midiId); hwButton.pressedAction().setPressureActionMatcher(midiIn.createNoteOnVelocityValueMatcher(0, midiId)); hwButton.releasedAction().setActionMatcher(midiIn.createNoteOffActionMatcher(0, midiId)); @@ -24,21 +24,22 @@ public RgbButton(final int midiId, String name, HardwareSurface surface, MidiPro hwButton.isPressed().markInterested(); light = surface.createMultiStateHardwareLight(name + "_LIGHT_" + midiId); light.state().setValue(RgbLightState.OFF); + light.setColorToStateFunction(RgbLightState::forColor); hwButton.isPressed().markInterested(); light.state().onUpdateHardware(this::updateState); } - private void updateState(InternalHardwareLightState state) { - if (state instanceof RgbColor rgbState) { + private void updateState(final InternalHardwareLightState state) { + if (state instanceof final RgbColor rgbState) { midiProcessor.updateColorPad(midiId, rgbState); } } - public void bindLight(Layer layer, final Supplier supplier) { + public void bindLight(final Layer layer, final Supplier supplier) { layer.bindLightState(supplier, this.light); } - public void bindDisabled(Layer layer) { + public void bindDisabled(final Layer layer) { this.bindLight(layer, () -> RgbColor.OFF); this.bindRelease(layer, () -> { }); diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/DrumButton.java b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/DrumButton.java index e3d3d6e9..d7fb99ea 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/DrumButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/DrumButton.java @@ -18,7 +18,6 @@ public DrumButton(final HardwareSurface surface, final MidiProcessor midiProcess initButtonNote(midiProcessor.getMidiIn(), notevalue); light.state().setValue(RgbState.of(0)); light.state().onUpdateHardware(this::updateState); - hwButton.setBackgroundLight(light); } private void updateState(final InternalHardwareLightState state) { diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/GridButton.java b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/GridButton.java index 9ad333a5..37cccad0 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/GridButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/GridButton.java @@ -14,7 +14,6 @@ public GridButton(final HardwareSurface surface, final MidiProcessor midiProcess initButtonNote(midiProcessor.getMidiIn(), notevalue); light.state().setValue(RgbState.of(0)); light.state().onUpdateHardware(this::updateState); - hwButton.setBackgroundLight(light); } private void updateState(final InternalHardwareLightState state) { diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LabeledButton.java b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LabeledButton.java index 3b9eb34e..0fbead9f 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LabeledButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LabeledButton.java @@ -11,7 +11,6 @@ public LabeledButton(final String name, final HardwareSurface surface, final Mid this.ccValue = ccValue; initButtonCc(midiProcessor.getMidiIn(), ccValue); light.state().onUpdateHardware(state -> midiProcessor.updatePadLed(state, ccValue)); - hwButton.setBackgroundLight(light); } public LabeledButton(final HardwareSurface surface, final MidiProcessor midiProcessor, @@ -20,7 +19,6 @@ public LabeledButton(final HardwareSurface surface, final MidiProcessor midiProc ccValue = ccAssignment.getCcValue(); initButtonCc(midiProcessor.getMidiIn(), ccAssignment); light.state().onUpdateHardware(state -> midiProcessor.updatePadLed(state, ccValue)); - hwButton.setBackgroundLight(light); } @Override diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LaunchPadButton.java b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LaunchPadButton.java index 5f217004..1f5144b9 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LaunchPadButton.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/LaunchPadButton.java @@ -1,22 +1,28 @@ package com.bitwig.extensions.controllers.novation.commonsmk3; -import com.bitwig.extension.controller.api.*; -import com.bitwig.extensions.framework.Layer; -import com.bitwig.extensions.framework.time.TimeRepeatEvent; -import com.bitwig.extensions.framework.time.TimedDelayEvent; -import com.bitwig.extensions.framework.time.TimedEvent; - import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import com.bitwig.extension.controller.api.BooleanValue; +import com.bitwig.extension.controller.api.HardwareButton; +import com.bitwig.extension.controller.api.HardwareSurface; +import com.bitwig.extension.controller.api.InternalHardwareLightState; +import com.bitwig.extension.controller.api.MidiIn; +import com.bitwig.extension.controller.api.MultiStateHardwareLight; +import com.bitwig.extension.controller.api.SettableBooleanValue; +import com.bitwig.extensions.framework.Layer; +import com.bitwig.extensions.framework.time.TimeRepeatEvent; +import com.bitwig.extensions.framework.time.TimedDelayEvent; +import com.bitwig.extensions.framework.time.TimedEvent; + public abstract class LaunchPadButton { public static final int STD_REPEAT_DELAY = 400; public static final int STD_REPEAT_FREQUENCY = 50; - protected HardwareButton hwButton; - protected MultiStateHardwareLight light; + protected final HardwareButton hwButton; + protected final MultiStateHardwareLight light; protected final MidiProcessor midiProcessor; protected final int channel; private TimedEvent currentTimer; @@ -30,6 +36,8 @@ protected LaunchPadButton(final String id, final HardwareSurface surface, final hwButton = surface.createHardwareButton(id); light = surface.createMultiStateHardwareLight(id + "-light"); light.state().setValue(RgbState.of(0)); + light.setColorToStateFunction(RgbState::forColor); + hwButton.setBackgroundLight(light); hwButton.isPressed().markInterested(); } diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/RgbState.java b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/RgbState.java index ca74a13b..61216bc9 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/RgbState.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/commonsmk3/RgbState.java @@ -1,11 +1,12 @@ package com.bitwig.extensions.controllers.novation.commonsmk3; -import com.bitwig.extension.controller.api.HardwareLightVisualState; -import com.bitwig.extension.controller.api.InternalHardwareLightState; - import java.util.HashMap; import java.util.Objects; +import com.bitwig.extension.api.Color; +import com.bitwig.extension.controller.api.HardwareLightVisualState; +import com.bitwig.extension.controller.api.InternalHardwareLightState; + public class RgbState extends InternalHardwareLightState { private static final RgbState[] registry = new RgbState[128]; @@ -36,6 +37,14 @@ public class RgbState extends InternalHardwareLightState { private final int altColorIndex; private LightState state; + public static RgbState forColor(final Color color) { + if (color == null || color.getAlpha() == 0) + return OFF; + + // TODO: Improve this + return WHITE; + } + private RgbState(final int colorIndex, final LightState state) { super(); this.colorIndex = colorIndex; diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Button.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Button.java index 7919f455..501bf432 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Button.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Button.java @@ -4,10 +4,8 @@ import com.bitwig.extension.controller.api.ControllerHost; import com.bitwig.extension.controller.api.HardwareButton; import com.bitwig.extension.controller.api.HardwareSurface; -import com.bitwig.extension.controller.api.InternalHardwareLightState; import com.bitwig.extension.controller.api.MidiIn; import com.bitwig.extension.controller.api.MultiStateHardwareLight; -import com.bitwig.extension.controller.api.ObjectHardwareProperty; final class Button { @@ -63,7 +61,8 @@ enum State final MultiStateHardwareLight light = hardwareSurface.createMultiStateHardwareLight(id + "-light"); light.state().setValue(LedState.OFF); - light.state().onUpdateHardware(internalHardwareLightState -> mDriver.updateButtonLed(Button.this)); + light.setColorToStateFunction(color -> new LedState(color)); + light.state().onUpdateHardware(internalHardwareLightState -> mDriver.updateButtonLed(Button.this, (LedState)internalHardwareLightState)); bt.setBackgroundLight(light); mButton = bt; @@ -100,21 +99,14 @@ boolean isPressed() return mButtonState == State.PRESSED || mButtonState == State.HOLD; } - public void appendLedUpdate( + public void appendLedUpdate(LedState ledState, final StringBuilder ledClear, final StringBuilder ledUpdate, final StringBuilder ledPulseUpdate) { - final ObjectHardwareProperty state = mLight.state(); - LedState currentState = (LedState)state.currentValue(); - final LedState lastSent = (LedState)state.lastSentValue(); + if (ledState == null) + ledState = LedState.OFF; - if (currentState == null) - currentState = LedState.OFF; - - if (lastSent != null && currentState.equals(lastSent)) - return; - - final Color color = currentState.mColor; - final int pulse = currentState.mPulse; + final Color color = ledState.mColor; + final int pulse = ledState.mPulse; if (pulse == NO_PULSE) { diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Color.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Color.java index 1c9a52d7..d43c65e1 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Color.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/Color.java @@ -126,6 +126,11 @@ public Color(final ColorValue value) this(value.red(), value.green(), value.blue()); } + public Color(final com.bitwig.extension.api.Color color) + { + this((float)color.getRed(), (float)color.getGreen(), (float)color.getBlue()); + } + public Color(final Color color, final float scale) { mRed = (byte) (color.mRed * scale); diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LaunchpadProControllerExtension.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LaunchpadProControllerExtension.java index 040e68e7..ca1dd344 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LaunchpadProControllerExtension.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LaunchpadProControllerExtension.java @@ -560,9 +560,9 @@ public void exit() mMidiOut.sendSysex("F0 00 20 29 02 10 0E 00 F7"); } - public void updateButtonLed(final Button button) + public void updateButtonLed(final Button button, final LedState ledState) { - button.appendLedUpdate(mLedClearSysexBuffer, mLedColorUpdateSysexBuffer, mLedPulseUpdateSysexBuffer); + button.appendLedUpdate(ledState, mLedClearSysexBuffer, mLedColorUpdateSysexBuffer, mLedPulseUpdateSysexBuffer); // Let's not send sysex that are too big if (mLedColorUpdateSysexBuffer.length() >= 4 * 3 * 48) diff --git a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LedState.java b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LedState.java index 36b70410..9c2dcde1 100644 --- a/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LedState.java +++ b/src/main/java/com/bitwig/extensions/controllers/novation/launchpad_pro/LedState.java @@ -84,15 +84,19 @@ final class LedState extends InternalHardwareLightState final static LedState SCALE_ON_COLOR = new LedState(Color.fromRgb255(50, 167, 202)); final static LedState SCALE_OFF_COLOR = new LedState(Color.scale(SCALE_ON_COLOR.mColor, 0.2f)); - public LedState(final ColorValue color) { this(new Color(color)); } - LedState(final Color color) + public LedState(final Color color) { - this(color, 0); + this(color, 1); + } + + public LedState(final com.bitwig.extension.api.Color color) + { + this(new Color(color)); } LedState(final Color color, final int pulse)