From fd2e9a004968f622d8219d3768c631ca008ef2e9 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 5 Sep 2020 23:47:05 +0200 Subject: [PATCH 1/2] Added color-extension to calculate the distance between two colors --- RGB.NET.Core/Extensions/ColorExtensions.cs | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 RGB.NET.Core/Extensions/ColorExtensions.cs diff --git a/RGB.NET.Core/Extensions/ColorExtensions.cs b/RGB.NET.Core/Extensions/ColorExtensions.cs new file mode 100644 index 0000000..15d0c80 --- /dev/null +++ b/RGB.NET.Core/Extensions/ColorExtensions.cs @@ -0,0 +1,30 @@ +using System; + +namespace RGB.NET.Core +{ + public static class ColorExtensions + { + #region Methods + + /// + /// Calculates the distance between the two given colors using the redmean algorithm. + /// For more infos check https://www.compuphase.com/cmetric.htm + /// + /// The start color of the distance calculation. + /// The end color fot the distance calculation. + /// + public static double DistanceTo(this Color color1, Color color2) + { + (_, byte r1, byte g1, byte b1) = color1.GetRGBBytes(); + (_, byte r2, byte g2, byte b2) = color2.GetRGBBytes(); + + long rmean = (r1 + r2) / 2; + long r = r1 - r2; + long g = g1 - g2; + long b = b1 - b2; + return Math.Sqrt((((512 + rmean) * r * r) >> 8) + (4 * g * g) + (((767 - rmean) * b * b) >> 8)); + } + + #endregion + } +} From f91d5e50605cebcad5c095b5f5092696f76160a5 Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sat, 5 Sep 2020 23:48:46 +0200 Subject: [PATCH 2/2] Added support for novation launchpad mk2 --- .../Attributes/LedIdMappingAttribute.cs | 35 +++ .../Enum/NovationDevices.cs | 10 +- .../Enum/NovationLedId.cs | 107 -------- .../Generic/LimitedColorUpdateQueue.cs | 4 +- .../Generic/MidiUpdateQueue.cs | 14 +- .../Generic/NovationRGBDevice.cs | 10 +- .../Generic/RGBColorUpdateQueue.cs | 195 ++++++++++++++ .../Helper/DictionaryExtension.cs | 10 - .../Helper/EnumExtension.cs | 7 + .../Helper/NovationLedIdExtension.cs | 47 ---- .../Launchpad/LaunchpadIdMapping.cs | 252 ++++++++++++------ .../Launchpad/LedIdMappings.cs | 8 + .../Launchpad/NovationLaunchpadRGBDevice.cs | 27 +- .../NovationLaunchpadRGBDeviceInfo.cs | 13 +- .../NovationDeviceProvider.cs | 7 +- 15 files changed, 474 insertions(+), 272 deletions(-) create mode 100644 RGB.NET.Devices.Novation/Attributes/LedIdMappingAttribute.cs delete mode 100644 RGB.NET.Devices.Novation/Enum/NovationLedId.cs create mode 100644 RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs delete mode 100644 RGB.NET.Devices.Novation/Helper/DictionaryExtension.cs delete mode 100644 RGB.NET.Devices.Novation/Helper/NovationLedIdExtension.cs create mode 100644 RGB.NET.Devices.Novation/Launchpad/LedIdMappings.cs diff --git a/RGB.NET.Devices.Novation/Attributes/LedIdMappingAttribute.cs b/RGB.NET.Devices.Novation/Attributes/LedIdMappingAttribute.cs new file mode 100644 index 0000000..3cda1aa --- /dev/null +++ b/RGB.NET.Devices.Novation/Attributes/LedIdMappingAttribute.cs @@ -0,0 +1,35 @@ +using System; + +namespace RGB.NET.Devices.Novation.Attributes +{ + /// + /// + /// Specifies the led id mapping of a field. + /// + [AttributeUsage(AttributeTargets.Field)] + internal class LedIdMappingAttribute : Attribute + { + #region Properties & Fields + + /// + /// Gets the led id mapping. + /// + internal LedIdMappings LedIdMapping { get; } + + #endregion + + #region Constructors + + /// + /// + /// Initializes a new instance of the class. + /// + /// The led id mapping. + internal LedIdMappingAttribute(LedIdMappings ledIdMapping) + { + this.LedIdMapping = ledIdMapping; + } + + #endregion + } +} diff --git a/RGB.NET.Devices.Novation/Enum/NovationDevices.cs b/RGB.NET.Devices.Novation/Enum/NovationDevices.cs index c9cf763..f1afa2c 100644 --- a/RGB.NET.Devices.Novation/Enum/NovationDevices.cs +++ b/RGB.NET.Devices.Novation/Enum/NovationDevices.cs @@ -13,9 +13,17 @@ namespace RGB.NET.Devices.Novation { [DeviceId("Launchpad S")] [ColorCapability(NovationColorCapabilities.LimitedRG)] + [LedIdMapping(LedIdMappings.Legacy)] LaunchpadS, + [DeviceId("Launchpad Mini")] [ColorCapability(NovationColorCapabilities.LimitedRG)] - LaunchpadMini + [LedIdMapping(LedIdMappings.Legacy)] + LaunchpadMini, + + [DeviceId("Launchpad MK2")] + [ColorCapability(NovationColorCapabilities.RGB)] + [LedIdMapping(LedIdMappings.Current)] + LaunchpadMK2 } } diff --git a/RGB.NET.Devices.Novation/Enum/NovationLedId.cs b/RGB.NET.Devices.Novation/Enum/NovationLedId.cs deleted file mode 100644 index 22f44c3..0000000 --- a/RGB.NET.Devices.Novation/Enum/NovationLedId.cs +++ /dev/null @@ -1,107 +0,0 @@ -// ReSharper disable InconsistentNaming -// ReSharper disable UnusedMember.Global - -#pragma warning disable 1591 // Missing XML comment for publicly visible type or member - -namespace RGB.NET.Devices.Novation -{ - /// - /// Contains list of all LEDs available for all Novation devices. - /// They are represented as Hex 0x[00][11] where [00] is the status flag, [1] the id of the led. - /// - //TODO DarthAffe 15.08.2017: Check if this is really correct for all devices - public enum NovationLedId - { - Invalid = -1, - - Grid1 = 0x9000, - Grid2 = 0x9001, - Grid3 = 0x9002, - Grid4 = 0x9003, - Grid5 = 0x9004, - Grid6 = 0x9005, - Grid7 = 0x9006, - Grid8 = 0x9007, - - Grid9 = 0x9010, - Grid10 = 0x9011, - Grid11 = 0x9012, - Grid12 = 0x9013, - Grid13 = 0x9014, - Grid14 = 0x9015, - Grid15 = 0x9016, - Grid16 = 0x9017, - - Grid17 = 0x9020, - Grid18 = 0x9021, - Grid19 = 0x9022, - Grid20 = 0x9023, - Grid21 = 0x9024, - Grid22 = 0x9025, - Grid23 = 0x9026, - Grid24 = 0x9027, - - Grid25 = 0x9030, - Grid26 = 0x9031, - Grid27 = 0x9032, - Grid28 = 0x9033, - Grid29 = 0x9034, - Grid30 = 0x9035, - Grid31 = 0x9036, - Grid32 = 0x9037, - - Grid33 = 0x9040, - Grid34 = 0x9041, - Grid35 = 0x9042, - Grid36 = 0x9043, - Grid37 = 0x9044, - Grid38 = 0x9045, - Grid39 = 0x9046, - Grid40 = 0x9047, - - Grid41 = 0x9050, - Grid42 = 0x9051, - Grid43 = 0x9052, - Grid44 = 0x9053, - Grid45 = 0x9054, - Grid46 = 0x9055, - Grid47 = 0x9056, - Grid48 = 0x9057, - - Grid49 = 0x9060, - Grid50 = 0x9061, - Grid51 = 0x9062, - Grid52 = 0x9063, - Grid53 = 0x9064, - Grid54 = 0x9065, - Grid55 = 0x9066, - Grid56 = 0x9067, - - Grid57 = 0x9070, - Grid58 = 0x9071, - Grid59 = 0x9072, - Grid60 = 0x9073, - Grid61 = 0x9074, - Grid62 = 0x9075, - Grid63 = 0x9076, - Grid64 = 0x9077, - - Up = 0xB068, - Down = 0xB069, - Left = 0xB06A, - Right = 0xB06B, - Session = 0xB06C, - User1 = 0xB06D, - User2 = 0xB06E, - Mix = 0xB06F, - - Scene1 = 0x9009, - Scene2 = 0x9019, - Scene3 = 0x9029, - Scene4 = 0x9039, - Scene5 = 0x9049, - Scene6 = 0x9059, - Scene7 = 0x9069, - Scene8 = 0x9079 - } -} diff --git a/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs index a3570c9..588e359 100644 --- a/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs +++ b/RGB.NET.Devices.Novation/Generic/LimitedColorUpdateQueue.cs @@ -28,8 +28,8 @@ namespace RGB.NET.Devices.Novation /// protected override ShortMessage CreateMessage(KeyValuePair data) { - NovationLedId ledId = (NovationLedId)data.Key; - return new ShortMessage(Convert.ToByte(ledId.GetStatus()), Convert.ToByte(ledId.GetId()), Convert.ToByte(ConvertColor(data.Value))); + (byte mode, byte id) = ((byte, byte))data.Key; + return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(data.Value))); } /// diff --git a/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs index 4dfafc9..6e34359 100644 --- a/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs +++ b/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs @@ -47,7 +47,12 @@ namespace RGB.NET.Devices.Novation /// Sends the specified message to the device this queue is performing updates for. /// /// The message to send. - protected virtual void SendMessage(ShortMessage message) => _outputDevice.SendShort(message.Message); + protected virtual void SendMessage(ShortMessage message) + { + if (message != null) + _outputDevice.SendShort(message.Message); + } + /// /// Creates a update-message out of a given data set. @@ -57,7 +62,12 @@ namespace RGB.NET.Devices.Novation protected abstract ShortMessage CreateMessage(KeyValuePair data); /// - public void Dispose() => _outputDevice.Dispose(); + public override void Dispose() + { + base.Dispose(); + + _outputDevice.Dispose(); + } #endregion } diff --git a/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs b/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs index a66fb03..d1f7679 100644 --- a/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Generic/NovationRGBDevice.cs @@ -57,8 +57,12 @@ namespace RGB.NET.Devices.Novation Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y); } - if (DeviceInfo.ColorCapabilities == NovationColorCapabilities.LimitedRG) - UpdateQueue = new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId); + UpdateQueue = DeviceInfo.ColorCapabilities switch + { + NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId), + NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId), + _ => throw new ArgumentOutOfRangeException() + }; } /// @@ -82,7 +86,7 @@ namespace RGB.NET.Devices.Novation try { UpdateQueue?.Dispose(); } catch { /* at least we tried */ } - + base.Dispose(); } diff --git a/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs new file mode 100644 index 0000000..5dd9d54 --- /dev/null +++ b/RGB.NET.Devices.Novation/Generic/RGBColorUpdateQueue.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using RGB.NET.Core; +using Sanford.Multimedia.Midi; + +namespace RGB.NET.Devices.Novation +{ + /// + /// Represents the update-queue performing updates for a RGB-color novation device. + /// + public class RGBColorUpdateQueue : MidiUpdateQueue + { + #region Properties & Fields + + private static readonly (Color, int)[] COLOR_PALETTE = + { + (new Color(0, 0, 0), 0), + (new Color(28, 28, 28), 1), + (new Color(124, 124, 124), 2), + (new Color(252, 252, 252), 3), + (new Color(255, 77, 71), 4), + (new Color(255, 10, 0), 5), + (new Color(90, 1, 0), 6), + (new Color(25, 0, 0), 7), + (new Color(255, 189, 98), 8), + (new Color(255, 86, 0), 9), + (new Color(90, 29, 0), 10), + (new Color(36, 24, 0), 11), + (new Color(253, 253, 33), 12), + (new Color(253, 253, 0), 13), + (new Color(88, 88, 0), 14), + (new Color(24, 24, 0), 15), + (new Color(128, 253, 42), 16), + (new Color(64, 253, 0), 17), + (new Color(22, 88, 0), 18), + (new Color(19, 40, 0), 19), + (new Color(52, 253, 43), 20), + (new Color(0, 253, 0), 21), + (new Color(0, 88, 0), 22), + (new Color(0, 24, 0), 23), + (new Color(51, 253, 70), 24), + (new Color(50, 253, 126), 28), + (new Color(0, 253, 58), 29), + (new Color(0, 88, 20), 30), + (new Color(0, 28, 15), 31), + (new Color(47, 252, 176), 32), + (new Color(0, 252, 145), 33), + (new Color(0, 88, 49), 34), + (new Color(0, 24, 15), 35), + (new Color(57, 191, 255), 36), + (new Color(0, 167, 255), 37), + (new Color(0, 64, 81), 38), + (new Color(0, 16, 24), 39), + (new Color(65, 134, 255), 40), + (new Color(0, 80, 255), 41), + (new Color(0, 26, 90), 42), + (new Color(0, 7, 25), 43), + (new Color(70, 71, 255), 44), + (new Color(0, 0, 255), 45), + (new Color(0, 0, 91), 46), + (new Color(0, 0, 25), 47), + (new Color(131, 71, 255), 48), + (new Color(80, 0, 255), 49), + (new Color(22, 0, 103), 50), + (new Color(11, 0, 50), 51), + (new Color(255, 73, 255), 52), + (new Color(255, 0, 255), 53), + (new Color(90, 0, 90), 54), + (new Color(25, 0, 25), 55), + (new Color(255, 77, 132), 56), + (new Color(255, 7, 82), 57), + (new Color(90, 1, 27), 58), + (new Color(33, 0, 16), 59), + (new Color(255, 25, 0), 60), + (new Color(155, 53, 0), 61), + (new Color(122, 81, 0), 62), + (new Color(62, 100, 0), 63), + (new Color(0, 56, 0), 64), + (new Color(0, 84, 50), 65), + (new Color(0, 83, 126), 66), + (new Color(0, 68, 77), 68), + (new Color(27, 0, 210), 69), + (new Color(32, 32, 32), 71), + (new Color(186, 253, 0), 73), + (new Color(170, 237, 0), 74), + (new Color(86, 253, 0), 75), + (new Color(0, 136, 0), 76), + (new Color(0, 252, 122), 77), + (new Color(0, 27, 255), 79), + (new Color(53, 0, 255), 80), + (new Color(119, 0, 255), 81), + (new Color(180, 23, 126), 82), + (new Color(65, 32, 0), 83), + (new Color(255, 74, 0), 84), + (new Color(131, 225, 0), 85), + (new Color(101, 253, 0), 86), + (new Color(69, 253, 97), 89), + (new Color(0, 252, 202), 90), + (new Color(80, 134, 255), 91), + (new Color(39, 77, 201), 92), + (new Color(130, 122, 237), 93), + (new Color(211, 12, 255), 94), + (new Color(255, 6, 90), 95), + (new Color(255, 125, 0), 96), + (new Color(185, 177, 0), 97), + (new Color(138, 253, 0), 98), + (new Color(130, 93, 0), 99), + (new Color(57, 40, 0), 100), + (new Color(13, 76, 5), 101), + (new Color(0, 80, 55), 102), + (new Color(19, 19, 41), 103), + (new Color(16, 31, 90), 104), + (new Color(106, 60, 23), 105), + (new Color(172, 4, 0), 106), + (new Color(225, 81, 53), 107), + (new Color(220, 105, 0), 108), + (new Color(255, 255, 0), 109), + (new Color(153, 225, 0), 110), + (new Color(95, 181, 0), 111), + (new Color(27, 27, 49), 112), + (new Color(220, 253, 84), 113), + (new Color(118, 252, 184), 114), + (new Color(150, 151, 255), 115), + (new Color(139, 97, 255), 116), + (new Color(64, 64, 64), 117), + (new Color(116, 116, 116), 118), + (new Color(222, 252, 252), 119), + (new Color(164, 4, 0), 120), + (new Color(53, 0, 0), 121), + (new Color(0, 209, 0), 122), + (new Color(0, 64, 0), 123), + (new Color(61, 48, 0), 125), + (new Color(180, 93, 0), 126), + (new Color(74, 20, 0), 127), + }; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The update trigger used by this queue. + /// The device-id of the device this queue is performing updates for. + public RGBColorUpdateQueue(IDeviceUpdateTrigger updateTrigger, int deviceId) + : base(updateTrigger, deviceId) + { } + + #endregion + + #region Methods + + /// + protected override ShortMessage CreateMessage(KeyValuePair data) + { + (byte mode, byte id) = ((byte, byte))data.Key; + if (mode == 0x00) return null; + + return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(data.Value))); + } + + /// + /// Convert a to its novation-representation depending on the of the . + /// Source: http://www.launchpadfun.com/downloads_de/velocity-colors/ + /// + /// The to convert. + /// The novation-representation of the . + protected virtual int ConvertColor(Color color) + { + int bestVelocity = 0; + double bestMatchDistance = double.MaxValue; + foreach ((Color c, int velocity) in COLOR_PALETTE) + { + double distance = c.DistanceTo(color); + if (distance < bestMatchDistance) + { + bestVelocity = velocity; + bestMatchDistance = distance; + } + } + + return bestVelocity; + } + + /// + public override void Reset() + { + base.Reset(); + SendMessage(new ShortMessage(Convert.ToByte(0xB0), Convert.ToByte(0), Convert.ToByte(0))); + } + + #endregion + } +} diff --git a/RGB.NET.Devices.Novation/Helper/DictionaryExtension.cs b/RGB.NET.Devices.Novation/Helper/DictionaryExtension.cs deleted file mode 100644 index 607ad97..0000000 --- a/RGB.NET.Devices.Novation/Helper/DictionaryExtension.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace RGB.NET.Devices.Novation -{ - internal static class DictionaryExtension - { - public static Dictionary SwapKeyValue(this Dictionary dictionary) => dictionary.ToDictionary(x => x.Value, x => x.Key); - } -} diff --git a/RGB.NET.Devices.Novation/Helper/EnumExtension.cs b/RGB.NET.Devices.Novation/Helper/EnumExtension.cs index 9be8305..a3f432a 100644 --- a/RGB.NET.Devices.Novation/Helper/EnumExtension.cs +++ b/RGB.NET.Devices.Novation/Helper/EnumExtension.cs @@ -23,6 +23,13 @@ namespace RGB.NET.Devices.Novation /// The value of the of the source. internal static NovationColorCapabilities GetColorCapability(this Enum source) => source.GetAttribute()?.Capability ?? NovationColorCapabilities.None; + /// + /// Gets the value of the . + /// + /// The enum value to get the description from. + /// The value of the of the source. + internal static LedIdMappings GetLedIdMapping(this Enum source) => source.GetAttribute()?.LedIdMapping ?? LedIdMappings.Current; + /// /// Gets the attribute of type T. /// diff --git a/RGB.NET.Devices.Novation/Helper/NovationLedIdExtension.cs b/RGB.NET.Devices.Novation/Helper/NovationLedIdExtension.cs deleted file mode 100644 index 7d8556c..0000000 --- a/RGB.NET.Devices.Novation/Helper/NovationLedIdExtension.cs +++ /dev/null @@ -1,47 +0,0 @@ -namespace RGB.NET.Devices.Novation -{ - /// - /// Offers some extensions and helper-methods for NovationLedId related things. - /// - public static class NovationLedIdExtension - { - #region Methods - - /// - /// Gets the status-flag associated with the id. - /// - /// The whose status-flag should be determinated. - /// The status-flag of the . - public static int GetStatus(this NovationLedId ledId) => ((int)ledId & 0xFF00) >> 8; - - /// - /// Gets the id associated with the id. - /// - /// The whose idshould be determinated. - /// The id of the . - public static int GetId(this NovationLedId ledId) => (int)ledId & 0x00FF; - - /// - /// Tests if the given is a grid-button. - /// - /// the to test. - /// true if is a grid-button; otherwise, false. - public static bool IsGrid(this NovationLedId ledId) => (ledId.GetStatus() == 0x90) && ((ledId.GetId() / 0x10) < 0x08) && ((ledId.GetId() % 0x10) < 0x08); - - /// - /// Tests if the given is a scene-button. - /// - /// the to test. - /// true if is a scene-button; otherwise, false. - public static bool IsScene(this NovationLedId ledId) => (ledId.GetStatus() == 0x90) && ((ledId.GetId() / 0x10) < 0x08) && ((ledId.GetId() % 0x10) == 0x09); - - /// - /// Tests if the given is custom-button. - /// - /// the to test. - /// true if is a custom-button; otherwise, false. - public static bool IsCustom(this NovationLedId ledId) => (ledId.GetStatus() == 0xB0) && ((ledId.GetId() / 0x10) == 0x06) && ((ledId.GetId() % 0x10) > 0x07); - - #endregion - } -} diff --git a/RGB.NET.Devices.Novation/Launchpad/LaunchpadIdMapping.cs b/RGB.NET.Devices.Novation/Launchpad/LaunchpadIdMapping.cs index 8d90205..39aa29f 100644 --- a/RGB.NET.Devices.Novation/Launchpad/LaunchpadIdMapping.cs +++ b/RGB.NET.Devices.Novation/Launchpad/LaunchpadIdMapping.cs @@ -5,92 +5,180 @@ namespace RGB.NET.Devices.Novation { internal static class LaunchpadIdMapping { - internal static readonly Dictionary DEFAULT = new Dictionary + internal static readonly Dictionary LEGACY = new Dictionary { - { LedId.Invalid, NovationLedId.Invalid }, + { LedId.Invalid, (0x00, 0xFF, 8, 0) }, - { LedId.LedMatrix1, NovationLedId.Grid1 }, - { LedId.LedMatrix2, NovationLedId.Grid2 }, - { LedId.LedMatrix3, NovationLedId.Grid3 }, - { LedId.LedMatrix4, NovationLedId.Grid4 }, - { LedId.LedMatrix5, NovationLedId.Grid5 }, - { LedId.LedMatrix6, NovationLedId.Grid6 }, - { LedId.LedMatrix7, NovationLedId.Grid7 }, - { LedId.LedMatrix8, NovationLedId.Grid8 }, - { LedId.LedMatrix9, NovationLedId.Grid9 }, - { LedId.LedMatrix10, NovationLedId.Grid10 }, - { LedId.LedMatrix11, NovationLedId.Grid11 }, - { LedId.LedMatrix12, NovationLedId.Grid12 }, - { LedId.LedMatrix13, NovationLedId.Grid13 }, - { LedId.LedMatrix14, NovationLedId.Grid14 }, - { LedId.LedMatrix15, NovationLedId.Grid15 }, - { LedId.LedMatrix16, NovationLedId.Grid16 }, - { LedId.LedMatrix17, NovationLedId.Grid17 }, - { LedId.LedMatrix18, NovationLedId.Grid18 }, - { LedId.LedMatrix19, NovationLedId.Grid19 }, - { LedId.LedMatrix20, NovationLedId.Grid20 }, - { LedId.LedMatrix21, NovationLedId.Grid21 }, - { LedId.LedMatrix22, NovationLedId.Grid22 }, - { LedId.LedMatrix23, NovationLedId.Grid23 }, - { LedId.LedMatrix24, NovationLedId.Grid24 }, - { LedId.LedMatrix25, NovationLedId.Grid25 }, - { LedId.LedMatrix26, NovationLedId.Grid26 }, - { LedId.LedMatrix27, NovationLedId.Grid27 }, - { LedId.LedMatrix28, NovationLedId.Grid28 }, - { LedId.LedMatrix29, NovationLedId.Grid29 }, - { LedId.LedMatrix30, NovationLedId.Grid30 }, - { LedId.LedMatrix31, NovationLedId.Grid31 }, - { LedId.LedMatrix32, NovationLedId.Grid32 }, - { LedId.LedMatrix33, NovationLedId.Grid33 }, - { LedId.LedMatrix34, NovationLedId.Grid34 }, - { LedId.LedMatrix35, NovationLedId.Grid35 }, - { LedId.LedMatrix36, NovationLedId.Grid36 }, - { LedId.LedMatrix37, NovationLedId.Grid37 }, - { LedId.LedMatrix38, NovationLedId.Grid38 }, - { LedId.LedMatrix39, NovationLedId.Grid39 }, - { LedId.LedMatrix40, NovationLedId.Grid40 }, - { LedId.LedMatrix41, NovationLedId.Grid41 }, - { LedId.LedMatrix42, NovationLedId.Grid42 }, - { LedId.LedMatrix43, NovationLedId.Grid43 }, - { LedId.LedMatrix44, NovationLedId.Grid44 }, - { LedId.LedMatrix45, NovationLedId.Grid45 }, - { LedId.LedMatrix46, NovationLedId.Grid46 }, - { LedId.LedMatrix47, NovationLedId.Grid47 }, - { LedId.LedMatrix48, NovationLedId.Grid48 }, - { LedId.LedMatrix49, NovationLedId.Grid49 }, - { LedId.LedMatrix50, NovationLedId.Grid50 }, - { LedId.LedMatrix51, NovationLedId.Grid51 }, - { LedId.LedMatrix52, NovationLedId.Grid52 }, - { LedId.LedMatrix53, NovationLedId.Grid53 }, - { LedId.LedMatrix54, NovationLedId.Grid54 }, - { LedId.LedMatrix55, NovationLedId.Grid55 }, - { LedId.LedMatrix56, NovationLedId.Grid56 }, - { LedId.LedMatrix57, NovationLedId.Grid57 }, - { LedId.LedMatrix58, NovationLedId.Grid58 }, - { LedId.LedMatrix59, NovationLedId.Grid59 }, - { LedId.LedMatrix60, NovationLedId.Grid60 }, - { LedId.LedMatrix61, NovationLedId.Grid61 }, - { LedId.LedMatrix62, NovationLedId.Grid62 }, - { LedId.LedMatrix63, NovationLedId.Grid63 }, - { LedId.LedMatrix64, NovationLedId.Grid64 }, + { LedId.LedMatrix1, (0x90, 0x00, 0, 1) }, + { LedId.LedMatrix2, (0x90, 0x01, 1, 1) }, + { LedId.LedMatrix3, (0x90, 0x02, 2, 1) }, + { LedId.LedMatrix4, (0x90, 0x03, 3, 1) }, + { LedId.LedMatrix5, (0x90, 0x04, 4, 1) }, + { LedId.LedMatrix6, (0x90, 0x05, 5, 1) }, + { LedId.LedMatrix7, (0x90, 0x06, 6, 1) }, + { LedId.LedMatrix8, (0x90, 0x07, 7, 1) }, + { LedId.LedMatrix9, (0x90, 0x10, 0, 2) }, + { LedId.LedMatrix10, (0x90, 0x11, 1, 2) }, + { LedId.LedMatrix11, (0x90, 0x12, 2, 2) }, + { LedId.LedMatrix12, (0x90, 0x13, 3, 2) }, + { LedId.LedMatrix13, (0x90, 0x14, 4, 2) }, + { LedId.LedMatrix14, (0x90, 0x15, 5, 2) }, + { LedId.LedMatrix15, (0x90, 0x16, 6, 2) }, + { LedId.LedMatrix16, (0x90, 0x17, 7, 2) }, + { LedId.LedMatrix17, (0x90, 0x20, 0, 3) }, + { LedId.LedMatrix18, (0x90, 0x21, 1, 3) }, + { LedId.LedMatrix19, (0x90, 0x22, 2, 3) }, + { LedId.LedMatrix20, (0x90, 0x23, 3, 3) }, + { LedId.LedMatrix21, (0x90, 0x24, 4, 3) }, + { LedId.LedMatrix22, (0x90, 0x25, 5, 3) }, + { LedId.LedMatrix23, (0x90, 0x26, 6, 3) }, + { LedId.LedMatrix24, (0x90, 0x27, 7, 3) }, + { LedId.LedMatrix25, (0x90, 0x30, 0, 4) }, + { LedId.LedMatrix26, (0x90, 0x31, 1, 4) }, + { LedId.LedMatrix27, (0x90, 0x32, 2, 4) }, + { LedId.LedMatrix28, (0x90, 0x33, 3, 4) }, + { LedId.LedMatrix29, (0x90, 0x34, 4, 4) }, + { LedId.LedMatrix30, (0x90, 0x35, 5, 4) }, + { LedId.LedMatrix31, (0x90, 0x36, 6, 4) }, + { LedId.LedMatrix32, (0x90, 0x37, 7, 4) }, + { LedId.LedMatrix33, (0x90, 0x40, 0, 5) }, + { LedId.LedMatrix34, (0x90, 0x41, 1, 5) }, + { LedId.LedMatrix35, (0x90, 0x42, 2, 5) }, + { LedId.LedMatrix36, (0x90, 0x43, 3, 5) }, + { LedId.LedMatrix37, (0x90, 0x44, 4, 5) }, + { LedId.LedMatrix38, (0x90, 0x45, 5, 5) }, + { LedId.LedMatrix39, (0x90, 0x46, 6, 5) }, + { LedId.LedMatrix40, (0x90, 0x47, 7, 5) }, + { LedId.LedMatrix41, (0x90, 0x50, 0, 6) }, + { LedId.LedMatrix42, (0x90, 0x51, 1, 6) }, + { LedId.LedMatrix43, (0x90, 0x52, 2, 6) }, + { LedId.LedMatrix44, (0x90, 0x53, 3, 6) }, + { LedId.LedMatrix45, (0x90, 0x54, 4, 6) }, + { LedId.LedMatrix46, (0x90, 0x55, 5, 6) }, + { LedId.LedMatrix47, (0x90, 0x56, 6, 6) }, + { LedId.LedMatrix48, (0x90, 0x57, 7, 6) }, + { LedId.LedMatrix49, (0x90, 0x60, 0, 7) }, + { LedId.LedMatrix50, (0x90, 0x61, 1, 7) }, + { LedId.LedMatrix51, (0x90, 0x62, 2, 7) }, + { LedId.LedMatrix52, (0x90, 0x63, 3, 7) }, + { LedId.LedMatrix53, (0x90, 0x64, 4, 7) }, + { LedId.LedMatrix54, (0x90, 0x65, 5, 7) }, + { LedId.LedMatrix55, (0x90, 0x66, 6, 7) }, + { LedId.LedMatrix56, (0x90, 0x67, 7, 7) }, + { LedId.LedMatrix57, (0x90, 0x70, 0, 8) }, + { LedId.LedMatrix58, (0x90, 0x71, 1, 8) }, + { LedId.LedMatrix59, (0x90, 0x72, 2, 8) }, + { LedId.LedMatrix60, (0x90, 0x73, 3, 8) }, + { LedId.LedMatrix61, (0x90, 0x74, 4, 8) }, + { LedId.LedMatrix62, (0x90, 0x75, 5, 8) }, + { LedId.LedMatrix63, (0x90, 0x76, 6, 8) }, + { LedId.LedMatrix64, (0x90, 0x77, 7, 8) }, - { LedId.Custom1, NovationLedId.Up }, - { LedId.Custom2, NovationLedId.Down }, - { LedId.Custom3, NovationLedId.Left }, - { LedId.Custom4, NovationLedId.Right }, - { LedId.Custom5, NovationLedId.Session }, - { LedId.Custom6, NovationLedId.User1 }, - { LedId.Custom7, NovationLedId.User2 }, - { LedId.Custom8, NovationLedId.Mix }, + { LedId.Custom1, (0xB0, 0x68, 0, 0) }, // Up + { LedId.Custom2, (0xB0, 0x69, 1, 0) }, // Down + { LedId.Custom3, (0xB0, 0x6A, 2, 0) }, // Left + { LedId.Custom4, (0xB0, 0x6B, 3, 0) }, // Right + { LedId.Custom5, (0xB0, 0x6C, 4, 0) }, // Session + { LedId.Custom6, (0xB0, 0x6D, 5, 0) }, // User 1 + { LedId.Custom7, (0xB0, 0x6E, 6, 0) }, // User 2 + { LedId.Custom8, (0xB0, 0x6F, 7, 0) }, // Mix - { LedId.Custom9, NovationLedId.Scene1 }, - { LedId.Custom10, NovationLedId.Scene2 }, - { LedId.Custom11, NovationLedId.Scene3 }, - { LedId.Custom12, NovationLedId.Scene4 }, - { LedId.Custom13, NovationLedId.Scene5 }, - { LedId.Custom14, NovationLedId.Scene6 }, - { LedId.Custom15, NovationLedId.Scene7 }, - { LedId.Custom16, NovationLedId.Scene8 }, + { LedId.Custom9, (0x90, 0x08, 8, 1) }, //Scene1 + { LedId.Custom10, (0x90, 0x18, 8, 2) }, //Scene2 + { LedId.Custom11, (0x90, 0x28, 8, 3) }, //Scene3 + { LedId.Custom12, (0x90, 0x38, 8, 4) }, //Scene4 + { LedId.Custom13, (0x90, 0x48, 8, 5) }, //Scene5 + { LedId.Custom14, (0x90, 0x58, 8, 6) }, //Scene6 + { LedId.Custom15, (0x90, 0x68, 8, 7) }, //Scene7 + { LedId.Custom16, (0x90, 0x78, 8, 8) }, //Scene8 + }; + + internal static readonly Dictionary CURRENT = new Dictionary + { + { LedId.Invalid, (0x00, 0xFF, 8, 0) }, + + { LedId.LedMatrix1, (0x90, 81, 0, 1) }, + { LedId.LedMatrix2, (0x90, 82, 1, 1) }, + { LedId.LedMatrix3, (0x90, 83, 2, 1) }, + { LedId.LedMatrix4, (0x90, 84, 3, 1) }, + { LedId.LedMatrix5, (0x90, 85, 4, 1) }, + { LedId.LedMatrix6, (0x90, 86, 5, 1) }, + { LedId.LedMatrix7, (0x90, 87, 6, 1) }, + { LedId.LedMatrix8, (0x90, 88, 7, 1) }, + { LedId.LedMatrix9, (0x90, 71, 0, 2) }, + { LedId.LedMatrix10, (0x90, 72, 1, 2) }, + { LedId.LedMatrix11, (0x90, 73, 2, 2) }, + { LedId.LedMatrix12, (0x90, 74, 3, 2) }, + { LedId.LedMatrix13, (0x90, 75, 4, 2) }, + { LedId.LedMatrix14, (0x90, 76, 5, 2) }, + { LedId.LedMatrix15, (0x90, 77, 6, 2) }, + { LedId.LedMatrix16, (0x90, 78, 7, 2) }, + { LedId.LedMatrix17, (0x90, 61, 0, 3) }, + { LedId.LedMatrix18, (0x90, 62, 1, 3) }, + { LedId.LedMatrix19, (0x90, 63, 2, 3) }, + { LedId.LedMatrix20, (0x90, 64, 3, 3) }, + { LedId.LedMatrix21, (0x90, 65, 4, 3) }, + { LedId.LedMatrix22, (0x90, 66, 5, 3) }, + { LedId.LedMatrix23, (0x90, 67, 6, 3) }, + { LedId.LedMatrix24, (0x90, 68, 7, 3) }, + { LedId.LedMatrix25, (0x90, 51, 0, 4) }, + { LedId.LedMatrix26, (0x90, 52, 1, 4) }, + { LedId.LedMatrix27, (0x90, 53, 2, 4) }, + { LedId.LedMatrix28, (0x90, 54, 3, 4) }, + { LedId.LedMatrix29, (0x90, 55, 4, 4) }, + { LedId.LedMatrix30, (0x90, 56, 5, 4) }, + { LedId.LedMatrix31, (0x90, 57, 6, 4) }, + { LedId.LedMatrix32, (0x90, 58, 7, 4) }, + { LedId.LedMatrix33, (0x90, 41, 0, 5) }, + { LedId.LedMatrix34, (0x90, 42, 1, 5) }, + { LedId.LedMatrix35, (0x90, 43, 2, 5) }, + { LedId.LedMatrix36, (0x90, 44, 3, 5) }, + { LedId.LedMatrix37, (0x90, 45, 4, 5) }, + { LedId.LedMatrix38, (0x90, 46, 5, 5) }, + { LedId.LedMatrix39, (0x90, 47, 6, 5) }, + { LedId.LedMatrix40, (0x90, 48, 7, 5) }, + { LedId.LedMatrix41, (0x90, 31, 0, 6) }, + { LedId.LedMatrix42, (0x90, 32, 1, 6) }, + { LedId.LedMatrix43, (0x90, 33, 2, 6) }, + { LedId.LedMatrix44, (0x90, 34, 3, 6) }, + { LedId.LedMatrix45, (0x90, 35, 4, 6) }, + { LedId.LedMatrix46, (0x90, 36, 5, 6) }, + { LedId.LedMatrix47, (0x90, 37, 6, 6) }, + { LedId.LedMatrix48, (0x90, 38, 7, 6) }, + { LedId.LedMatrix49, (0x90, 21, 0, 7) }, + { LedId.LedMatrix50, (0x90, 22, 1, 7) }, + { LedId.LedMatrix51, (0x90, 23, 2, 7) }, + { LedId.LedMatrix52, (0x90, 24, 3, 7) }, + { LedId.LedMatrix53, (0x90, 25, 4, 7) }, + { LedId.LedMatrix54, (0x90, 26, 5, 7) }, + { LedId.LedMatrix55, (0x90, 27, 6, 7) }, + { LedId.LedMatrix56, (0x90, 28, 7, 7) }, + { LedId.LedMatrix57, (0x90, 11, 0, 8) }, + { LedId.LedMatrix58, (0x90, 12, 1, 8) }, + { LedId.LedMatrix59, (0x90, 13, 2, 8) }, + { LedId.LedMatrix60, (0x90, 14, 3, 8) }, + { LedId.LedMatrix61, (0x90, 15, 4, 8) }, + { LedId.LedMatrix62, (0x90, 16, 5, 8) }, + { LedId.LedMatrix63, (0x90, 17, 6, 8) }, + { LedId.LedMatrix64, (0x90, 18, 7, 8) }, + + { LedId.Custom1, (0xB0, 104, 0, 0) }, // Up + { LedId.Custom2, (0xB0, 105, 1, 0) }, // Down + { LedId.Custom3, (0xB0, 106, 2, 0) }, // Left + { LedId.Custom4, (0xB0, 107, 3, 0) }, // Right + { LedId.Custom5, (0xB0, 108, 4, 0) }, // Session + { LedId.Custom6, (0xB0, 109, 5, 0) }, // User 1 + { LedId.Custom7, (0xB0, 110, 6, 0) }, // User 2 + { LedId.Custom8, (0xB0, 111, 7, 0) }, // Mix + + { LedId.Custom9, (0x90, 89, 8, 1) }, //Scene1 + { LedId.Custom10, (0x90, 79, 8, 2) }, //Scene2 + { LedId.Custom11, (0x90, 69, 8, 3) }, //Scene3 + { LedId.Custom12, (0x90, 59, 8, 4) }, //Scene4 + { LedId.Custom13, (0x90, 49, 8, 5) }, //Scene5 + { LedId.Custom14, (0x90, 39, 8, 6) }, //Scene6 + { LedId.Custom15, (0x90, 29, 8, 7) }, //Scene7 + { LedId.Custom16, (0x90, 19, 8, 8) }, //Scene8 }; } } diff --git a/RGB.NET.Devices.Novation/Launchpad/LedIdMappings.cs b/RGB.NET.Devices.Novation/Launchpad/LedIdMappings.cs new file mode 100644 index 0000000..e264f1a --- /dev/null +++ b/RGB.NET.Devices.Novation/Launchpad/LedIdMappings.cs @@ -0,0 +1,8 @@ +namespace RGB.NET.Devices.Novation +{ + internal enum LedIdMappings + { + Current, + Legacy + } +} diff --git a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs index 3eabdf5..e00f114 100644 --- a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs +++ b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDevice.cs @@ -28,22 +28,13 @@ namespace RGB.NET.Devices.Novation /// protected override void InitializeLayout() { - Dictionary mapping = LaunchpadIdMapping.DEFAULT.SwapKeyValue(); + Dictionary mapping = GetDeviceMapping(); - //TODO DarthAffe 15.08.2017: Check if all launchpads are using the same basic layout const int BUTTON_SIZE = 20; - foreach (NovationLedId ledId in Enum.GetValues(typeof(NovationLedId))) + foreach (LedId ledId in mapping.Keys) { - Rectangle rectangle; - if (ledId.IsCustom()) - rectangle = new Rectangle(BUTTON_SIZE * (ledId.GetId() - 0x68), 0, BUTTON_SIZE, BUTTON_SIZE); - else if (ledId.IsScene()) - rectangle = new Rectangle(8 * BUTTON_SIZE, BUTTON_SIZE * (((int)ledId.GetId() / 0x10) + 1), BUTTON_SIZE, BUTTON_SIZE); - else if (ledId.IsGrid()) - rectangle = new Rectangle(BUTTON_SIZE * ((int)ledId.GetId() % 0x10), BUTTON_SIZE * (((int)ledId.GetId() / 0x10) + 1), BUTTON_SIZE, BUTTON_SIZE); - else continue; - - InitializeLed(mapping[ledId], rectangle); + (_, _, int x, int y) = mapping[ledId]; + InitializeLed(ledId, new Point(BUTTON_SIZE * x, BUTTON_SIZE * y), new Size(BUTTON_SIZE)); } string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); @@ -51,7 +42,15 @@ namespace RGB.NET.Devices.Novation } /// - protected override object CreateLedCustomData(LedId ledId) => LaunchpadIdMapping.DEFAULT.TryGetValue(ledId, out NovationLedId novationLedId) ? novationLedId : NovationLedId.Invalid; + protected override object CreateLedCustomData(LedId ledId) => GetDeviceMapping().TryGetValue(ledId, out (byte mode, byte id, int _, int __) data) ? (data.mode, data.id) : ((byte)0x00, (byte)0x00); + + protected virtual Dictionary GetDeviceMapping() + => DeviceInfo.LedIdMapping switch + { + LedIdMappings.Current => LaunchpadIdMapping.CURRENT, + LedIdMappings.Legacy => LaunchpadIdMapping.LEGACY, + _ => throw new ArgumentOutOfRangeException() + }; #endregion } diff --git a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDeviceInfo.cs b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDeviceInfo.cs index b854c26..ce86e05 100644 --- a/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDeviceInfo.cs +++ b/RGB.NET.Devices.Novation/Launchpad/NovationLaunchpadRGBDeviceInfo.cs @@ -8,6 +8,12 @@ namespace RGB.NET.Devices.Novation /// public class NovationLaunchpadRGBDeviceInfo : NovationRGBDeviceInfo { + #region Properties & Fields + + internal LedIdMappings LedIdMapping { get; } + + #endregion + #region Constructors /// @@ -17,9 +23,12 @@ namespace RGB.NET.Devices.Novation /// The represented device model. /// /// The of the . - internal NovationLaunchpadRGBDeviceInfo(string model, int deviceId, NovationColorCapabilities colorCapabilities) + internal NovationLaunchpadRGBDeviceInfo(string model, int deviceId, NovationColorCapabilities colorCapabilities, + LedIdMappings ledIdMapping) : base(RGBDeviceType.LedMatrix, model, deviceId, colorCapabilities) - { } + { + this.LedIdMapping = ledIdMapping; + } #endregion } diff --git a/RGB.NET.Devices.Novation/NovationDeviceProvider.cs b/RGB.NET.Devices.Novation/NovationDeviceProvider.cs index b7890e8..4e031fe 100644 --- a/RGB.NET.Devices.Novation/NovationDeviceProvider.cs +++ b/RGB.NET.Devices.Novation/NovationDeviceProvider.cs @@ -85,11 +85,14 @@ namespace RGB.NET.Devices.Novation NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices)) .Cast() - .FirstOrDefault(x => string.Equals(x.GetDeviceId(), outCaps.name, StringComparison.OrdinalIgnoreCase)); + .FirstOrDefault(x => x.GetDeviceId().ToUpperInvariant().Contains(outCaps.name.ToUpperInvariant())); if (deviceId == null) continue; - INovationRGBDevice device = new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, deviceId.GetColorCapability())); + NovationColorCapabilities colorCapability = deviceId.GetColorCapability(); + if (colorCapability == NovationColorCapabilities.None) continue; + + INovationRGBDevice device = new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping())); device.Initialize(UpdateTrigger); devices.Add(device); }