1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 10:08:31 +00:00

Merge pull request #150 from DarthAffe/SDK/Novation

Sdk/novation
This commit is contained in:
DarthAffe 2020-10-04 12:18:42 +02:00 committed by GitHub
commit efe8f4da2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 504 additions and 272 deletions

View File

@ -0,0 +1,30 @@
using System;
namespace RGB.NET.Core
{
public static class ColorExtensions
{
#region Methods
/// <summary>
/// Calculates the distance between the two given colors using the redmean algorithm.
/// For more infos check https://www.compuphase.com/cmetric.htm
/// </summary>
/// <param name="color1">The start color of the distance calculation.</param>
/// <param name="color2">The end color fot the distance calculation.</param>
/// <returns></returns>
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
}
}

View File

@ -0,0 +1,35 @@
using System;
namespace RGB.NET.Devices.Novation.Attributes
{
/// <inheritdoc />
/// <summary>
/// Specifies the led id mapping of a field.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
internal class LedIdMappingAttribute : Attribute
{
#region Properties & Fields
/// <summary>
/// Gets the led id mapping.
/// </summary>
internal LedIdMappings LedIdMapping { get; }
#endregion
#region Constructors
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Novation.Attributes.LedIdMappingAttribute" /> class.
/// </summary>
/// <param name="ledIdMapping">The led id mapping.</param>
internal LedIdMappingAttribute(LedIdMappings ledIdMapping)
{
this.LedIdMapping = ledIdMapping;
}
#endregion
}
}

View File

@ -13,9 +13,17 @@ namespace RGB.NET.Devices.Novation
{ {
[DeviceId("Launchpad S")] [DeviceId("Launchpad S")]
[ColorCapability(NovationColorCapabilities.LimitedRG)] [ColorCapability(NovationColorCapabilities.LimitedRG)]
[LedIdMapping(LedIdMappings.Legacy)]
LaunchpadS, LaunchpadS,
[DeviceId("Launchpad Mini")] [DeviceId("Launchpad Mini")]
[ColorCapability(NovationColorCapabilities.LimitedRG)] [ColorCapability(NovationColorCapabilities.LimitedRG)]
LaunchpadMini [LedIdMapping(LedIdMappings.Legacy)]
LaunchpadMini,
[DeviceId("Launchpad MK2")]
[ColorCapability(NovationColorCapabilities.RGB)]
[LedIdMapping(LedIdMappings.Current)]
LaunchpadMK2
} }
} }

View File

@ -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
{
/// <summary>
/// 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.
/// </summary>
//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
}
}

View File

@ -28,8 +28,8 @@ namespace RGB.NET.Devices.Novation
/// <inheritdoc /> /// <inheritdoc />
protected override ShortMessage CreateMessage(KeyValuePair<object, Color> data) protected override ShortMessage CreateMessage(KeyValuePair<object, Color> data)
{ {
NovationLedId ledId = (NovationLedId)data.Key; (byte mode, byte id) = ((byte, byte))data.Key;
return new ShortMessage(Convert.ToByte(ledId.GetStatus()), Convert.ToByte(ledId.GetId()), Convert.ToByte(ConvertColor(data.Value))); return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(data.Value)));
} }
/// <summary> /// <summary>

View File

@ -47,7 +47,12 @@ namespace RGB.NET.Devices.Novation
/// Sends the specified message to the device this queue is performing updates for. /// Sends the specified message to the device this queue is performing updates for.
/// </summary> /// </summary>
/// <param name="message">The message to send.</param> /// <param name="message">The message to send.</param>
protected virtual void SendMessage(ShortMessage message) => _outputDevice.SendShort(message.Message); protected virtual void SendMessage(ShortMessage message)
{
if (message != null)
_outputDevice.SendShort(message.Message);
}
/// <summary> /// <summary>
/// Creates a update-message out of a given data set. /// Creates a update-message out of a given data set.
@ -57,7 +62,12 @@ namespace RGB.NET.Devices.Novation
protected abstract ShortMessage CreateMessage(KeyValuePair<object, Color> data); protected abstract ShortMessage CreateMessage(KeyValuePair<object, Color> data);
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() => _outputDevice.Dispose(); public override void Dispose()
{
base.Dispose();
_outputDevice.Dispose();
}
#endregion #endregion
} }

View File

@ -57,8 +57,12 @@ namespace RGB.NET.Devices.Novation
Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y); Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
} }
if (DeviceInfo.ColorCapabilities == NovationColorCapabilities.LimitedRG) UpdateQueue = DeviceInfo.ColorCapabilities switch
UpdateQueue = new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId); {
NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId),
NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId),
_ => throw new ArgumentOutOfRangeException()
};
} }
/// <summary> /// <summary>
@ -82,7 +86,7 @@ namespace RGB.NET.Devices.Novation
try { UpdateQueue?.Dispose(); } try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ } catch { /* at least we tried */ }
base.Dispose(); base.Dispose();
} }

View File

@ -0,0 +1,195 @@
using System;
using System.Collections.Generic;
using RGB.NET.Core;
using Sanford.Multimedia.Midi;
namespace RGB.NET.Devices.Novation
{
/// <summary>
/// Represents the update-queue performing updates for a RGB-color novation device.
/// </summary>
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
/// <summary>
/// Initializes a new instance of the <see cref="RGBColorUpdateQueue"/> class.
/// </summary>
/// <param name="updateTrigger">The update trigger used by this queue.</param>
/// <param name="deviceId">The device-id of the device this queue is performing updates for.</param>
public RGBColorUpdateQueue(IDeviceUpdateTrigger updateTrigger, int deviceId)
: base(updateTrigger, deviceId)
{ }
#endregion
#region Methods
/// <inheritdoc />
protected override ShortMessage CreateMessage(KeyValuePair<object, Color> data)
{
(byte mode, byte id) = ((byte, byte))data.Key;
if (mode == 0x00) return null;
return new ShortMessage(mode, id, Convert.ToByte(ConvertColor(data.Value)));
}
/// <summary>
/// Convert a <see cref="Color"/> to its novation-representation depending on the <see cref="NovationColorCapabilities"/> of the <see cref="NovationRGBDevice{TDeviceInfo}"/>.
/// Source: http://www.launchpadfun.com/downloads_de/velocity-colors/
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert.</param>
/// <returns>The novation-representation of the <see cref="Color"/>.</returns>
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;
}
/// <inheritdoc />
public override void Reset()
{
base.Reset();
SendMessage(new ShortMessage(Convert.ToByte(0xB0), Convert.ToByte(0), Convert.ToByte(0)));
}
#endregion
}
}

View File

@ -1,10 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace RGB.NET.Devices.Novation
{
internal static class DictionaryExtension
{
public static Dictionary<TValue, TKey> SwapKeyValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary) => dictionary.ToDictionary(x => x.Value, x => x.Key);
}
}

View File

@ -23,6 +23,13 @@ namespace RGB.NET.Devices.Novation
/// <returns>The value of the <see cref="ColorCapabilityAttribute"/> of the source.</returns> /// <returns>The value of the <see cref="ColorCapabilityAttribute"/> of the source.</returns>
internal static NovationColorCapabilities GetColorCapability(this Enum source) => source.GetAttribute<ColorCapabilityAttribute>()?.Capability ?? NovationColorCapabilities.None; internal static NovationColorCapabilities GetColorCapability(this Enum source) => source.GetAttribute<ColorCapabilityAttribute>()?.Capability ?? NovationColorCapabilities.None;
/// <summary>
/// Gets the value of the <see cref="LedIdMappingAttribute"/>.
/// </summary>
/// <param name="source">The enum value to get the description from.</param>
/// <returns>The value of the <see cref="LedIdMappingAttribute"/> of the source.</returns>
internal static LedIdMappings GetLedIdMapping(this Enum source) => source.GetAttribute<LedIdMappingAttribute>()?.LedIdMapping ?? LedIdMappings.Current;
/// <summary> /// <summary>
/// Gets the attribute of type T. /// Gets the attribute of type T.
/// </summary> /// </summary>

View File

@ -1,47 +0,0 @@
namespace RGB.NET.Devices.Novation
{
/// <summary>
/// Offers some extensions and helper-methods for NovationLedId related things.
/// </summary>
public static class NovationLedIdExtension
{
#region Methods
/// <summary>
/// Gets the status-flag associated with the id.
/// </summary>
/// <param name="ledId">The <see cref="NovationLedId"/> whose status-flag should be determinated.</param>
/// <returns>The status-flag of the <see cref="NovationLedId"/>.</returns>
public static int GetStatus(this NovationLedId ledId) => ((int)ledId & 0xFF00) >> 8;
/// <summary>
/// Gets the id associated with the id.
/// </summary>
/// <param name="ledId">The <see cref="NovationLedId"/> whose idshould be determinated.</param>
/// <returns>The id of the <see cref="NovationLedId"/>.</returns>
public static int GetId(this NovationLedId ledId) => (int)ledId & 0x00FF;
/// <summary>
/// Tests if the given <see cref="NovationLedId"/> is a grid-button.
/// </summary>
/// <param name="ledId">the <see cref="NovationLedId"/> to test.</param>
/// <returns><c>true</c> if <paramref name="ledId" /> is a grid-button; otherwise, <c>false</c>.</returns>
public static bool IsGrid(this NovationLedId ledId) => (ledId.GetStatus() == 0x90) && ((ledId.GetId() / 0x10) < 0x08) && ((ledId.GetId() % 0x10) < 0x08);
/// <summary>
/// Tests if the given <see cref="NovationLedId"/> is a scene-button.
/// </summary>
/// <param name="ledId">the <see cref="NovationLedId"/> to test.</param>
/// <returns><c>true</c> if <paramref name="ledId" /> is a scene-button; otherwise, <c>false</c>.</returns>
public static bool IsScene(this NovationLedId ledId) => (ledId.GetStatus() == 0x90) && ((ledId.GetId() / 0x10) < 0x08) && ((ledId.GetId() % 0x10) == 0x09);
/// <summary>
/// Tests if the given <see cref="NovationLedId"/> is custom-button.
/// </summary>
/// <param name="ledId">the <see cref="NovationLedId"/> to test.</param>
/// <returns><c>true</c> if <paramref name="ledId" /> is a custom-button; otherwise, <c>false</c>.</returns>
public static bool IsCustom(this NovationLedId ledId) => (ledId.GetStatus() == 0xB0) && ((ledId.GetId() / 0x10) == 0x06) && ((ledId.GetId() % 0x10) > 0x07);
#endregion
}
}

View File

@ -5,92 +5,180 @@ namespace RGB.NET.Devices.Novation
{ {
internal static class LaunchpadIdMapping internal static class LaunchpadIdMapping
{ {
internal static readonly Dictionary<LedId, NovationLedId> DEFAULT = new Dictionary<LedId, NovationLedId> internal static readonly Dictionary<LedId, (byte mode, byte id, int x, int y)> LEGACY = new Dictionary<LedId, (byte mode, byte id, int x, int y)>
{ {
{ LedId.Invalid, NovationLedId.Invalid }, { LedId.Invalid, (0x00, 0xFF, 8, 0) },
{ LedId.LedMatrix1, NovationLedId.Grid1 }, { LedId.LedMatrix1, (0x90, 0x00, 0, 1) },
{ LedId.LedMatrix2, NovationLedId.Grid2 }, { LedId.LedMatrix2, (0x90, 0x01, 1, 1) },
{ LedId.LedMatrix3, NovationLedId.Grid3 }, { LedId.LedMatrix3, (0x90, 0x02, 2, 1) },
{ LedId.LedMatrix4, NovationLedId.Grid4 }, { LedId.LedMatrix4, (0x90, 0x03, 3, 1) },
{ LedId.LedMatrix5, NovationLedId.Grid5 }, { LedId.LedMatrix5, (0x90, 0x04, 4, 1) },
{ LedId.LedMatrix6, NovationLedId.Grid6 }, { LedId.LedMatrix6, (0x90, 0x05, 5, 1) },
{ LedId.LedMatrix7, NovationLedId.Grid7 }, { LedId.LedMatrix7, (0x90, 0x06, 6, 1) },
{ LedId.LedMatrix8, NovationLedId.Grid8 }, { LedId.LedMatrix8, (0x90, 0x07, 7, 1) },
{ LedId.LedMatrix9, NovationLedId.Grid9 }, { LedId.LedMatrix9, (0x90, 0x10, 0, 2) },
{ LedId.LedMatrix10, NovationLedId.Grid10 }, { LedId.LedMatrix10, (0x90, 0x11, 1, 2) },
{ LedId.LedMatrix11, NovationLedId.Grid11 }, { LedId.LedMatrix11, (0x90, 0x12, 2, 2) },
{ LedId.LedMatrix12, NovationLedId.Grid12 }, { LedId.LedMatrix12, (0x90, 0x13, 3, 2) },
{ LedId.LedMatrix13, NovationLedId.Grid13 }, { LedId.LedMatrix13, (0x90, 0x14, 4, 2) },
{ LedId.LedMatrix14, NovationLedId.Grid14 }, { LedId.LedMatrix14, (0x90, 0x15, 5, 2) },
{ LedId.LedMatrix15, NovationLedId.Grid15 }, { LedId.LedMatrix15, (0x90, 0x16, 6, 2) },
{ LedId.LedMatrix16, NovationLedId.Grid16 }, { LedId.LedMatrix16, (0x90, 0x17, 7, 2) },
{ LedId.LedMatrix17, NovationLedId.Grid17 }, { LedId.LedMatrix17, (0x90, 0x20, 0, 3) },
{ LedId.LedMatrix18, NovationLedId.Grid18 }, { LedId.LedMatrix18, (0x90, 0x21, 1, 3) },
{ LedId.LedMatrix19, NovationLedId.Grid19 }, { LedId.LedMatrix19, (0x90, 0x22, 2, 3) },
{ LedId.LedMatrix20, NovationLedId.Grid20 }, { LedId.LedMatrix20, (0x90, 0x23, 3, 3) },
{ LedId.LedMatrix21, NovationLedId.Grid21 }, { LedId.LedMatrix21, (0x90, 0x24, 4, 3) },
{ LedId.LedMatrix22, NovationLedId.Grid22 }, { LedId.LedMatrix22, (0x90, 0x25, 5, 3) },
{ LedId.LedMatrix23, NovationLedId.Grid23 }, { LedId.LedMatrix23, (0x90, 0x26, 6, 3) },
{ LedId.LedMatrix24, NovationLedId.Grid24 }, { LedId.LedMatrix24, (0x90, 0x27, 7, 3) },
{ LedId.LedMatrix25, NovationLedId.Grid25 }, { LedId.LedMatrix25, (0x90, 0x30, 0, 4) },
{ LedId.LedMatrix26, NovationLedId.Grid26 }, { LedId.LedMatrix26, (0x90, 0x31, 1, 4) },
{ LedId.LedMatrix27, NovationLedId.Grid27 }, { LedId.LedMatrix27, (0x90, 0x32, 2, 4) },
{ LedId.LedMatrix28, NovationLedId.Grid28 }, { LedId.LedMatrix28, (0x90, 0x33, 3, 4) },
{ LedId.LedMatrix29, NovationLedId.Grid29 }, { LedId.LedMatrix29, (0x90, 0x34, 4, 4) },
{ LedId.LedMatrix30, NovationLedId.Grid30 }, { LedId.LedMatrix30, (0x90, 0x35, 5, 4) },
{ LedId.LedMatrix31, NovationLedId.Grid31 }, { LedId.LedMatrix31, (0x90, 0x36, 6, 4) },
{ LedId.LedMatrix32, NovationLedId.Grid32 }, { LedId.LedMatrix32, (0x90, 0x37, 7, 4) },
{ LedId.LedMatrix33, NovationLedId.Grid33 }, { LedId.LedMatrix33, (0x90, 0x40, 0, 5) },
{ LedId.LedMatrix34, NovationLedId.Grid34 }, { LedId.LedMatrix34, (0x90, 0x41, 1, 5) },
{ LedId.LedMatrix35, NovationLedId.Grid35 }, { LedId.LedMatrix35, (0x90, 0x42, 2, 5) },
{ LedId.LedMatrix36, NovationLedId.Grid36 }, { LedId.LedMatrix36, (0x90, 0x43, 3, 5) },
{ LedId.LedMatrix37, NovationLedId.Grid37 }, { LedId.LedMatrix37, (0x90, 0x44, 4, 5) },
{ LedId.LedMatrix38, NovationLedId.Grid38 }, { LedId.LedMatrix38, (0x90, 0x45, 5, 5) },
{ LedId.LedMatrix39, NovationLedId.Grid39 }, { LedId.LedMatrix39, (0x90, 0x46, 6, 5) },
{ LedId.LedMatrix40, NovationLedId.Grid40 }, { LedId.LedMatrix40, (0x90, 0x47, 7, 5) },
{ LedId.LedMatrix41, NovationLedId.Grid41 }, { LedId.LedMatrix41, (0x90, 0x50, 0, 6) },
{ LedId.LedMatrix42, NovationLedId.Grid42 }, { LedId.LedMatrix42, (0x90, 0x51, 1, 6) },
{ LedId.LedMatrix43, NovationLedId.Grid43 }, { LedId.LedMatrix43, (0x90, 0x52, 2, 6) },
{ LedId.LedMatrix44, NovationLedId.Grid44 }, { LedId.LedMatrix44, (0x90, 0x53, 3, 6) },
{ LedId.LedMatrix45, NovationLedId.Grid45 }, { LedId.LedMatrix45, (0x90, 0x54, 4, 6) },
{ LedId.LedMatrix46, NovationLedId.Grid46 }, { LedId.LedMatrix46, (0x90, 0x55, 5, 6) },
{ LedId.LedMatrix47, NovationLedId.Grid47 }, { LedId.LedMatrix47, (0x90, 0x56, 6, 6) },
{ LedId.LedMatrix48, NovationLedId.Grid48 }, { LedId.LedMatrix48, (0x90, 0x57, 7, 6) },
{ LedId.LedMatrix49, NovationLedId.Grid49 }, { LedId.LedMatrix49, (0x90, 0x60, 0, 7) },
{ LedId.LedMatrix50, NovationLedId.Grid50 }, { LedId.LedMatrix50, (0x90, 0x61, 1, 7) },
{ LedId.LedMatrix51, NovationLedId.Grid51 }, { LedId.LedMatrix51, (0x90, 0x62, 2, 7) },
{ LedId.LedMatrix52, NovationLedId.Grid52 }, { LedId.LedMatrix52, (0x90, 0x63, 3, 7) },
{ LedId.LedMatrix53, NovationLedId.Grid53 }, { LedId.LedMatrix53, (0x90, 0x64, 4, 7) },
{ LedId.LedMatrix54, NovationLedId.Grid54 }, { LedId.LedMatrix54, (0x90, 0x65, 5, 7) },
{ LedId.LedMatrix55, NovationLedId.Grid55 }, { LedId.LedMatrix55, (0x90, 0x66, 6, 7) },
{ LedId.LedMatrix56, NovationLedId.Grid56 }, { LedId.LedMatrix56, (0x90, 0x67, 7, 7) },
{ LedId.LedMatrix57, NovationLedId.Grid57 }, { LedId.LedMatrix57, (0x90, 0x70, 0, 8) },
{ LedId.LedMatrix58, NovationLedId.Grid58 }, { LedId.LedMatrix58, (0x90, 0x71, 1, 8) },
{ LedId.LedMatrix59, NovationLedId.Grid59 }, { LedId.LedMatrix59, (0x90, 0x72, 2, 8) },
{ LedId.LedMatrix60, NovationLedId.Grid60 }, { LedId.LedMatrix60, (0x90, 0x73, 3, 8) },
{ LedId.LedMatrix61, NovationLedId.Grid61 }, { LedId.LedMatrix61, (0x90, 0x74, 4, 8) },
{ LedId.LedMatrix62, NovationLedId.Grid62 }, { LedId.LedMatrix62, (0x90, 0x75, 5, 8) },
{ LedId.LedMatrix63, NovationLedId.Grid63 }, { LedId.LedMatrix63, (0x90, 0x76, 6, 8) },
{ LedId.LedMatrix64, NovationLedId.Grid64 }, { LedId.LedMatrix64, (0x90, 0x77, 7, 8) },
{ LedId.Custom1, NovationLedId.Up }, { LedId.Custom1, (0xB0, 0x68, 0, 0) }, // Up
{ LedId.Custom2, NovationLedId.Down }, { LedId.Custom2, (0xB0, 0x69, 1, 0) }, // Down
{ LedId.Custom3, NovationLedId.Left }, { LedId.Custom3, (0xB0, 0x6A, 2, 0) }, // Left
{ LedId.Custom4, NovationLedId.Right }, { LedId.Custom4, (0xB0, 0x6B, 3, 0) }, // Right
{ LedId.Custom5, NovationLedId.Session }, { LedId.Custom5, (0xB0, 0x6C, 4, 0) }, // Session
{ LedId.Custom6, NovationLedId.User1 }, { LedId.Custom6, (0xB0, 0x6D, 5, 0) }, // User 1
{ LedId.Custom7, NovationLedId.User2 }, { LedId.Custom7, (0xB0, 0x6E, 6, 0) }, // User 2
{ LedId.Custom8, NovationLedId.Mix }, { LedId.Custom8, (0xB0, 0x6F, 7, 0) }, // Mix
{ LedId.Custom9, NovationLedId.Scene1 }, { LedId.Custom9, (0x90, 0x08, 8, 1) }, //Scene1
{ LedId.Custom10, NovationLedId.Scene2 }, { LedId.Custom10, (0x90, 0x18, 8, 2) }, //Scene2
{ LedId.Custom11, NovationLedId.Scene3 }, { LedId.Custom11, (0x90, 0x28, 8, 3) }, //Scene3
{ LedId.Custom12, NovationLedId.Scene4 }, { LedId.Custom12, (0x90, 0x38, 8, 4) }, //Scene4
{ LedId.Custom13, NovationLedId.Scene5 }, { LedId.Custom13, (0x90, 0x48, 8, 5) }, //Scene5
{ LedId.Custom14, NovationLedId.Scene6 }, { LedId.Custom14, (0x90, 0x58, 8, 6) }, //Scene6
{ LedId.Custom15, NovationLedId.Scene7 }, { LedId.Custom15, (0x90, 0x68, 8, 7) }, //Scene7
{ LedId.Custom16, NovationLedId.Scene8 }, { LedId.Custom16, (0x90, 0x78, 8, 8) }, //Scene8
};
internal static readonly Dictionary<LedId, (byte mode, byte id, int x, int y)> CURRENT = new Dictionary<LedId, (byte mode, byte id, int x, int y)>
{
{ 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
}; };
} }
} }

View File

@ -0,0 +1,8 @@
namespace RGB.NET.Devices.Novation
{
internal enum LedIdMappings
{
Current,
Legacy
}
}

View File

@ -28,22 +28,13 @@ namespace RGB.NET.Devices.Novation
/// <inheritdoc /> /// <inheritdoc />
protected override void InitializeLayout() protected override void InitializeLayout()
{ {
Dictionary<NovationLedId, LedId> mapping = LaunchpadIdMapping.DEFAULT.SwapKeyValue(); Dictionary<LedId, (byte mode, byte id, int x, int y)> mapping = GetDeviceMapping();
//TODO DarthAffe 15.08.2017: Check if all launchpads are using the same basic layout
const int BUTTON_SIZE = 20; const int BUTTON_SIZE = 20;
foreach (NovationLedId ledId in Enum.GetValues(typeof(NovationLedId))) foreach (LedId ledId in mapping.Keys)
{ {
Rectangle rectangle; (_, _, int x, int y) = mapping[ledId];
if (ledId.IsCustom()) InitializeLed(ledId, new Point(BUTTON_SIZE * x, BUTTON_SIZE * y), new Size(BUTTON_SIZE));
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);
} }
string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper(); string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
@ -51,7 +42,15 @@ namespace RGB.NET.Devices.Novation
} }
/// <inheritdoc /> /// <inheritdoc />
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<LedId, (byte mode, byte id, int x, int y)> GetDeviceMapping()
=> DeviceInfo.LedIdMapping switch
{
LedIdMappings.Current => LaunchpadIdMapping.CURRENT,
LedIdMappings.Legacy => LaunchpadIdMapping.LEGACY,
_ => throw new ArgumentOutOfRangeException()
};
#endregion #endregion
} }

View File

@ -8,6 +8,12 @@ namespace RGB.NET.Devices.Novation
/// </summary> /// </summary>
public class NovationLaunchpadRGBDeviceInfo : NovationRGBDeviceInfo public class NovationLaunchpadRGBDeviceInfo : NovationRGBDeviceInfo
{ {
#region Properties & Fields
internal LedIdMappings LedIdMapping { get; }
#endregion
#region Constructors #region Constructors
/// <inheritdoc /> /// <inheritdoc />
@ -17,9 +23,12 @@ namespace RGB.NET.Devices.Novation
/// <param name="model">The represented device model.</param> /// <param name="model">The represented device model.</param>
/// <param name="deviceId"></param> /// <param name="deviceId"></param>
/// <param name="colorCapabilities">The <see cref="T:RGB.NET.Devices.Novation.NovationColorCapabilities" /> of the <see cref="T:RGB.NET.Core.IRGBDevice" />.</param> /// <param name="colorCapabilities">The <see cref="T:RGB.NET.Devices.Novation.NovationColorCapabilities" /> of the <see cref="T:RGB.NET.Core.IRGBDevice" />.</param>
internal NovationLaunchpadRGBDeviceInfo(string model, int deviceId, NovationColorCapabilities colorCapabilities) internal NovationLaunchpadRGBDeviceInfo(string model, int deviceId, NovationColorCapabilities colorCapabilities,
LedIdMappings ledIdMapping)
: base(RGBDeviceType.LedMatrix, model, deviceId, colorCapabilities) : base(RGBDeviceType.LedMatrix, model, deviceId, colorCapabilities)
{ } {
this.LedIdMapping = ledIdMapping;
}
#endregion #endregion
} }

View File

@ -85,11 +85,14 @@ namespace RGB.NET.Devices.Novation
NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices)) NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices))
.Cast<Enum>() .Cast<Enum>()
.FirstOrDefault(x => string.Equals(x.GetDeviceId(), outCaps.name, StringComparison.OrdinalIgnoreCase)); .FirstOrDefault(x => x.GetDeviceId().ToUpperInvariant().Contains(outCaps.name.ToUpperInvariant()));
if (deviceId == null) continue; 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); device.Initialize(UpdateTrigger);
devices.Add(device); devices.Add(device);
} }