diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java index 971674a1105103c029cf319691fe08f2c9a6331c..8f85c706314a1e57850c02b07e6342f8468408b7 100644 --- a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/impl/LaunchpadPluginImpl.java @@ -6,6 +6,7 @@ import de.thecodelabs.plugins.PluginDescriptor; import de.thecodelabs.plugins.versionizer.PluginArtifact; import de.thecodelabs.utils.util.Localization; import de.tobias.playpad.launchpadplugin.midi.mk2.LaunchPadMK2; +import de.tobias.playpad.launchpadplugin.midi.mk3mini.LaunchPadMK3Mini; import de.tobias.playpad.launchpadplugin.midi.s.LaunchPadS; import de.tobias.playpad.plugin.Module; import de.tobias.playpad.plugin.PlayPadPluginStub; @@ -23,6 +24,8 @@ public class LaunchpadPluginImpl implements PlayPadPluginStub, PluginArtifact { final MidiFeedbackTranscriptionRegistry registry = MidiFeedbackTranscriptionRegistry.getInstance(); registry.register(LaunchPadMK2.NAME, new LaunchPadMK2()); registry.register(LaunchPadMK2.NATIVE_NAME, new LaunchPadMK2()); + registry.register(LaunchPadMK3Mini.NAME, new LaunchPadMK3Mini()); + registry.register(LaunchPadMK3Mini.NATIVE_NAME, new LaunchPadMK3Mini()); registry.register(LaunchPadS.NAME, new LaunchPadS()); registry.register(LaunchPadS.NATIVE_NAME, new LaunchPadS()); diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk3mini/LaunchPadMK3Color.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk3mini/LaunchPadMK3Color.java new file mode 100644 index 0000000000000000000000000000000000000000..ef5eff591f4ec4e3fd76c7e9e9a536f3e8d7ef09 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk3mini/LaunchPadMK3Color.java @@ -0,0 +1,121 @@ +package de.tobias.playpad.launchpadplugin.midi.mk3mini; + +import de.thecodelabs.midi.feedback.FeedbackColor; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; + +public enum LaunchPadMK3Color implements FeedbackColor { + + /* + High + Normal + Low + */ + + // White + C0_3(3, Color.rgb(255, 255, 255)), + C0_2(2, Color.rgb(255, 255, 255).darker()), + C0_1(1, Color.rgb(255, 255, 255).darker().darker()), + + // RED + C1_1(5, Color.rgb(255, 0, 0)), + C1_2(6, Color.rgb(255, 0, 0).darker()), + C1_3(7, Color.rgb(255, 0, 0).darker().darker()), + + // Orange + C2_1(9, Color.rgb(255, 127, 0)), + C2_2(10, Color.rgb(255, 127, 0).darker()), + C2_3(11, Color.rgb(255, 127, 0).darker().darker()), + + // LIME + C3_1(13, Color.rgb(235, 255, 39)), + C3_2(14, Color.rgb(235, 255, 39).darker()), + C3_3(15, Color.rgb(235, 255, 39).darker().darker()), + + // LIGHT GREEN + C4_1(17, Color.rgb(123, 255, 66)), + C4_2(18, Color.rgb(123, 255, 66).darker()), + C4_3(19, Color.rgb(123, 255, 66).darker().darker()), + + // GREEN + C5_1(21, Color.rgb(0, 255, 0)), + C5_2(22, Color.rgb(0, 255, 0).darker()), + C5_3(23, Color.rgb(0, 255, 0).darker().darker()), + + // GREEN + C6_1(25, Color.rgb(62, 255, 112)), + C6_2(26, Color.rgb(62, 255, 112).darker()), + C6_3(27, Color.rgb(62, 255, 112).darker().darker()), + + // TURKEY + C7_1(29, Color.rgb(62, 255, 112)), + C7_2(30, Color.rgb(62, 255, 112).darker()), + C7_3(31, Color.rgb(62, 255, 112).darker().darker()), + + // TURKEY + C8_1(33, Color.rgb(101, 255, 196)), + C8_2(34, Color.rgb(101, 255, 196).darker()), + C8_3(35, Color.rgb(101, 255, 196).darker().darker()), + + // LIGHT BLUE + C9_1(37, Color.rgb(91, 255, 253)), + C9_2(38, Color.rgb(91, 255, 253).darker()), + C9_3(39, Color.rgb(91, 255, 253).darker().darker()), + + // BLUE + C10_1(41, Color.rgb(69, 169, 255)), + C10_2(42, Color.rgb(69, 169, 255).darker()), + C10_3(43, Color.rgb(69, 169, 255).darker().darker()), + + // DARK BLUE + C11_1(45, Color.rgb(30, 67, 255)), + C11_2(46, Color.rgb(30, 67, 255).darker()), + C11_3(47, Color.rgb(30, 67, 255).darker().darker()), + + // PURPLE + C12_1(49, Color.rgb(125, 73, 255)), + C12_2(50, Color.rgb(125, 73, 255).darker()), + C12_3(51, Color.rgb(125, 73, 255).darker().darker()), + + // VIOLET + C13_1(53, Color.rgb(254, 85, 255)), + C13_2(54, Color.rgb(254, 85, 255).darker()), + C13_3(55, Color.rgb(254, 85, 255).darker().darker()), + + // VIOLET + C14_1(57, Color.rgb(255, 75, 191)), + C14_2(58, Color.rgb(255, 75, 191).darker()), + C14_3(59, Color.rgb(255, 75, 191).darker().darker()), + + // BROWN + C15_1(61, Color.rgb(255, 100, 69)), + C15_2(62, Color.rgb(255, 100, 69).darker()), + C15_3(63, Color.rgb(255, 100, 69).darker().darker()); + + private final int midi; + private final Color color; + + LaunchPadMK3Color(int midi, Color color) { + this.midi = midi; + this.color = color; + } + + @Override + public Paint getColor() { + return color; + } + + @Override + public byte getValue() { + return (byte) midi; + } + + public static FeedbackColor valueOf(int id) { + for (LaunchPadMK3Color color : values()) { + if (color.getValue() == id) { + return color; + } + } + return null; + } +} diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk3mini/LaunchPadMK3Mini.java b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk3mini/LaunchPadMK3Mini.java new file mode 100644 index 0000000000000000000000000000000000000000..3ddbcf434f1c843c0994623edbe8c5f2d4ef77fc --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/java/de/tobias/playpad/launchpadplugin/midi/mk3mini/LaunchPadMK3Mini.java @@ -0,0 +1,138 @@ +package de.tobias.playpad.launchpadplugin.midi.mk3mini; + +import de.thecodelabs.logger.Logger; +import de.thecodelabs.midi.feedback.Feedback; +import de.thecodelabs.midi.feedback.FeedbackColor; +import de.thecodelabs.midi.feedback.FeedbackType; +import de.thecodelabs.midi.feedback.FeedbackValue; +import de.thecodelabs.midi.mapping.MidiKey; +import de.thecodelabs.midi.midi.Midi; +import de.thecodelabs.midi.midi.MidiCommand; +import de.thecodelabs.midi.midi.MidiCommandType; +import de.thecodelabs.midi.midi.MidiDeviceListener; +import de.thecodelabs.midi.midi.feedback.MidiFeedbackTranscript; +import de.tobias.playpad.action.feedback.FeedbackColorSuggester; +import de.tobias.playpad.launchpadplugin.impl.MapParser; +import de.tobias.playpad.profile.Profile; +import javafx.scene.paint.Color; + +import java.net.URL; +import java.util.*; + +public class LaunchPadMK3Mini implements MidiFeedbackTranscript, FeedbackColorSuggester, MidiDeviceListener { + + public static final String NAME = "LPMiniMK3 MIDI"; + public static final String NATIVE_NAME = "CoreMIDI4J - Launchpad Mini MK3 LPMiniMK3 MIDI"; + + // Modern Colors mapped to the colors of the launchpad + private static final String[] COLOR_MAPPING_FILES = { + "launchpad_mk3_mini_colorful.map", + "launchpad_mk3_mini_high.map", + "launchpad_mk3_mini_normal.map", + "launchpad_mk3_mini_low.map" + }; + private static final String DEFAULT_COLOR_MAPPING = COLOR_MAPPING_FILES[0]; + private static final Map<String, Map<String, FeedbackColor>> midiColorMappings; + + static { + midiColorMappings = new HashMap<>(); + try { + for (String mappingFile : COLOR_MAPPING_FILES) { + URL resource = LaunchPadMK3Mini.class.getClassLoader().getResource(mappingFile); + midiColorMappings.put(mappingFile, MapParser.load(resource, LaunchPadMK3Color.class)); + } + } catch (Exception e) { + Logger.error(e); + } + } + + @Override + public void clearFeedback() { + final int maxMainKeyNumber = 89; + + for (byte i = 11; i <= maxMainKeyNumber; i++) { + Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.NOTE_ON, i, (byte) 0)); + } + + // Obere Reihe an Tasten + final int liveKeyMin = 104; + final int liveKeyMax = 111; + + for (byte i = liveKeyMin; i <= liveKeyMax; i++) { + Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, i, (byte) 0)); + } + } + + @Override + public void sendFeedback(MidiKey midiKey, FeedbackType feedbackType) { + final byte key = midiKey.getValue(); + + if (feedbackType == FeedbackType.NONE) { + if (key >= 104 && key <= 111) { + Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, key, (byte) 0)); + } else { + Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.NOTE_ON, key, (byte) 0)); + } + } + + Feedback feedback = midiKey.getFeedbackForType(feedbackType); + + if (feedback == null) { + return; + } + + final byte value = feedback.getValue(); + + if (key >= 104 && key <= 111) { + Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.CONTROL_CHANGE, key, value)); + } else { + if (feedbackType == FeedbackType.WARNING) { + sendFeedback(midiKey, FeedbackType.DEFAULT); + } + Midi.getInstance().sendMessage(new MidiCommand(MidiCommandType.NOTE_ON, feedback.getChannel(), key, value)); + } + } + + @Override + public FeedbackValue[] getFeedbackValues() { + String midiColorMapping = Profile.currentProfile().getProfileSettings().getMidiColorMapping(); + if (midiColorMapping == null || midiColorMapping.isEmpty()) { + midiColorMapping = DEFAULT_COLOR_MAPPING; + } + final Map<String, FeedbackColor> colorMap = midiColorMappings.get(midiColorMapping); + return colorMap.values().stream().sorted().distinct().toArray(FeedbackColor[]::new); + } + + @Override + public Optional<FeedbackValue> getFeedbackValueOfByte(byte b) { + return Optional.ofNullable(LaunchPadMK3Color.valueOf(b)); + } + + /* + FeedbackColorSuggester + */ + + @Override + public List<String> getMidiColorMappings() { + return Arrays.asList(COLOR_MAPPING_FILES); + } + + @Override + public FeedbackColor suggest(Color color) { + final String midiColorMapping = Optional.ofNullable(Profile.currentProfile().getProfileSettings().getMidiColorMapping()) + .orElse(DEFAULT_COLOR_MAPPING); + final Map<String, FeedbackColor> colorMap = midiColorMappings.get(midiColorMapping); + + if (colorMap.containsKey(color.toString())) { + return colorMap.get(color.toString()); + } + return null; + } + + @Override + public void onConnectionOpen() { + Midi.getInstance().sendMessage(new MidiCommand(new byte[]{(byte) 240, 126, 127, 6, 1, (byte) 247})); + Midi.getInstance().sendMessage(new MidiCommand(new byte[]{(byte) 240, 0, 32, 41, 2, 13, 0, 127, (byte) 247})); + Midi.getInstance().sendMessage(new MidiCommand(new byte[]{(byte) 240, 0, 32, 41, 2, 13, 14, 1, (byte) 247})); + } +} diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/lang/l10n.properties b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/lang/l10n.properties index c0cbfcf89b21f43273678ef74426a9257d53e83e..5d95fd8bddd8a37084ceca637be8b9a1781ddecc 100644 --- a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/lang/l10n.properties +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/lang/l10n.properties @@ -2,3 +2,8 @@ MidiColorMapping.launchpad_mk2_colorful.map=Farbenfroh MidiColorMapping.launchpad_mk2_high.map=Hell MidiColorMapping.launchpad_mk2_normal.map=Normal MidiColorMapping.launchpad_mk2_low.map=Dunkel + +MidiColorMapping.launchpad_mk3_mini_colorful.map=Farbenfroh +MidiColorMapping.launchpad_mk3_mini_high.map=Hell +MidiColorMapping.launchpad_mk3_mini_low.map=Normal +MidiColorMapping.launchpad_mk3_mini_normal.map=Dunkel diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_colorful.map b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_colorful.map new file mode 100644 index 0000000000000000000000000000000000000000..e7c0ea99f1f837cfe84282fcbb9c707d5d4d64cc --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_colorful.map @@ -0,0 +1,57 @@ +% RED +0xef9a9aff=C1_3 +0xef5350ff=C1_2 +0xe53935ff=C1_1 + +% DARK_RED +0xd92349ff=C1_3 +0xc92349ff=C1_2 +0xa90329ff=C1_1 + +% PINK +0xf48fb1ff=C14_3 +0xec407aff=C14_2 +0xd81b60ff=C14_1 + +% PURPLE +0xce93d8ff=C12_3 +0xab47bcff=C12_2 +0x8e24aaff=C12_1 + +% LIGHT_BLUE +0x80deeaff=C10_3 +0x26c6daff=C10_2 +0x00acc1ff=C10_1 + +% BLUE +0x90caf9ff=C11_3 +0x42a5f5ff=C11_2 +0x1e88e5ff=C11_1 + +% LIGHT_GREEN +0xc5e1a5ff=C5_3 +0x9ccc65ff=C5_2 +0x7cb342ff=C5_1 + +% LIME +0xe6ee9cff=C4_3 +0xd4e157ff=C4_2 +0xc0ca33ff=C4_1 + +% YELLOW +0xfff59dff=C3_3 +0xffee58ff=C3_2 +0xfdd835ff=C3_1 + +% ORANGE +0xffcc80ff=C2_3 +0xffa726ff=C2_2 +0xfb8c00ff=C2_1 + +% GRAY +0xeeeeeeff=C0_3 +0xccccccff=C0_3 +0xaaaaaaff=C0_3 +0x888888ff=C0_2 +0x666666ff=C0_2 +0x444444ff=C0_1 \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_high.map b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_high.map new file mode 100644 index 0000000000000000000000000000000000000000..4f6532323fd9c3767adaa9936c7b28dd4d5c4cd6 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_high.map @@ -0,0 +1,57 @@ +% RED +0xef9a9aff=C1_1 +0xef5350ff=C1_1 +0xe53935ff=C1_1 + +% DARK_RED +0xd92349ff=C1_1 +0xc92349ff=C1_1 +0xa90329ff=C1_1 + +% PINK +0xf48fb1ff=C14_1 +0xec407aff=C14_1 +0xd81b60ff=C14_1 + +% PURPLE +0xce93d8ff=C12_1 +0xab47bcff=C12_1 +0x8e24aaff=C12_1 + +% LIGHT_BLUE +0x80deeaff=C10_1 +0x26c6daff=C10_1 +0x00acc1ff=C10_1 + +% BLUE +0x90caf9ff=C11_1 +0x42a5f5ff=C11_1 +0x1e88e5ff=C11_1 + +% LIGHT_GREEN +0xc5e1a5ff=C5_1 +0x9ccc65ff=C5_1 +0x7cb342ff=C5_1 + +% LIME +0xe6ee9cff=C4_1 +0xd4e157ff=C4_1 +0xc0ca33ff=C4_1 + +% YELLOW +0xfff59dff=C3_1 +0xffee58ff=C3_1 +0xfdd835ff=C3_1 + +% ORANGE +0xffcc80ff=C2_1 +0xffa726ff=C2_1 +0xfb8c00ff=C2_1 + +% GRAY +0xeeeeeeff=C0_3 +0xccccccff=C0_3 +0xaaaaaaff=C0_3 +0x888888ff=C0_2 +0x666666ff=C0_2 +0x444444ff=C0_1 \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_low.map b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_low.map new file mode 100644 index 0000000000000000000000000000000000000000..34053852f3be518718bf5f982b255aa695b131b6 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_low.map @@ -0,0 +1,57 @@ +% RED +0xef9a9aff=C1_3 +0xef5350ff=C1_3 +0xe53935ff=C1_3 + +% DARK_RED +0xd92349ff=C1_3 +0xc92349ff=C1_3 +0xa90329ff=C1_3 + +% PINK +0xf48fb1ff=C14_3 +0xec407aff=C14_3 +0xd81b60ff=C14_3 + +% PURPLE +0xce93d8ff=C12_3 +0xab47bcff=C12_3 +0x8e24aaff=C12_3 + +% LIGHT_BLUE +0x80deeaff=C10_3 +0x26c6daff=C10_3 +0x00acc1ff=C10_3 + +% BLUE +0x90caf9ff=C11_3 +0x42a5f5ff=C11_3 +0x1e88e5ff=C11_3 + +% LIGHT_GREEN +0xc5e1a5ff=C5_3 +0x9ccc65ff=C5_3 +0x7cb342ff=C5_3 + +% LIME +0xe6ee9cff=C4_3 +0xd4e157ff=C4_3 +0xc0ca33ff=C4_3 + +% YELLOW +0xfff59dff=C3_3 +0xffee58ff=C3_3 +0xfdd835ff=C3_3 + +% ORANGE +0xffcc80ff=C2_3 +0xffa726ff=C2_3 +0xfb8c00ff=C2_3 + +% GRAY +0xeeeeeeff=C0_3 +0xccccccff=C0_3 +0xaaaaaaff=C0_3 +0x888888ff=C0_2 +0x666666ff=C0_2 +0x444444ff=C0_1 \ No newline at end of file diff --git a/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_normal.map b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_normal.map new file mode 100644 index 0000000000000000000000000000000000000000..8ab039471cdd4999aa4a59cd591c75b5138221d9 --- /dev/null +++ b/PlayWallPlugins/PlayWallPluginLaunchpad/src/main/resources/launchpad_mk3_mini_normal.map @@ -0,0 +1,57 @@ +% RED +0xef9a9aff=C1_2 +0xef5350ff=C1_2 +0xe53935ff=C1_2 + +% DARK_RED +0xd92349ff=C1_2 +0xc92349ff=C1_2 +0xa90329ff=C1_2 + +% PINK +0xf48fb1ff=C14_2 +0xec407aff=C14_2 +0xd81b60ff=C14_2 + +% PURPLE +0xce93d8ff=C12_2 +0xab47bcff=C12_2 +0x8e24aaff=C12_2 + +% LIGHT_BLUE +0x80deeaff=C10_2 +0x26c6daff=C10_2 +0x00acc1ff=C10_2 + +% BLUE +0x90caf9ff=C11_2 +0x42a5f5ff=C11_2 +0x1e88e5ff=C11_2 + +% LIGHT_GREEN +0xc5e1a5ff=C5_2 +0x9ccc65ff=C5_2 +0x7cb342ff=C5_2 + +% LIME +0xe6ee9cff=C4_2 +0xd4e157ff=C4_2 +0xc0ca33ff=C4_2 + +% YELLOW +0xfff59dff=C3_2 +0xffee58ff=C3_2 +0xfdd835ff=C3_2 + +% ORANGE +0xffcc80ff=C2_2 +0xffa726ff=C2_2 +0xfb8c00ff=C2_2 + +% GRAY +0xeeeeeeff=C0_3 +0xccccccff=C0_3 +0xaaaaaaff=C0_3 +0x888888ff=C0_2 +0x666666ff=C0_2 +0x444444ff=C0_1 \ No newline at end of file