1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 01:58:30 +00:00

Merge pull request #107 from DarthAffe/SDK/MSI

Sdk/msi
This commit is contained in:
DarthAffe 2020-02-23 15:21:13 +01:00 committed by GitHub
commit 745d60f871
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 280 additions and 38 deletions

View File

@ -34,6 +34,7 @@ namespace RGB.NET.Devices.Msi.Exceptions
/// <param name="errorCode">The raw error code provided by the SDK.</param>
/// <param name="description">The text-description of the error.</param>
public MysticLightException(int errorCode, string description)
: base($"MSI error code {errorCode} ({description})")
{
this.ErrorCode = errorCode;
this.Description = description;

View File

@ -3,10 +3,10 @@
namespace RGB.NET.Devices.Msi
{
/// <summary>
/// Represents a msi RGB-device.
/// Represents a MSI RGB-device.
/// </summary>
internal interface IMsiRGBDevice : IRGBDevice
{
void Initialize();
void Initialize(MsiDeviceUpdateQueue updateQueue, int ledCount);
}
}

View File

@ -0,0 +1,45 @@
using System.Collections.Generic;
using RGB.NET.Core;
using RGB.NET.Devices.Msi.Native;
namespace RGB.NET.Devices.Msi
{
/// <inheritdoc />
/// <summary>
/// Represents the update-queue performing updates for MSI devices.
/// </summary>
public class MsiDeviceUpdateQueue : UpdateQueue
{
#region Properties & Fields
private string _deviceType;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="MsiDeviceUpdateQueue"/> class.
/// </summary>
/// <param name="updateTrigger">The update trigger used by this queue.</param>
/// <param name="deviceType">The device-type used to identify the device.</param>
public MsiDeviceUpdateQueue(IDeviceUpdateTrigger updateTrigger, string deviceType)
: base(updateTrigger)
{
this._deviceType = deviceType;
}
#endregion
#region Methods
/// <inheritdoc />
protected override void Update(Dictionary<object, Color> dataSet)
{
foreach (KeyValuePair<object, Color> data in dataSet)
_MsiSDK.SetLedColor(_deviceType, (int)data.Key, data.Value.GetR(), data.Value.GetG(), data.Value.GetB());
}
#endregion
}
}

View File

@ -1,14 +1,13 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.Msi.Native;
namespace RGB.NET.Devices.Msi
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="IMsiRGBDevice" />
/// <summary>
/// Represents a generic Msi-device. (keyboard, mouse, headset, mousepad).
/// Represents a generic MSI-device. (keyboard, mouse, headset, mousepad).
/// </summary>
public abstract class MsiRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IMsiRGBDevice
where TDeviceInfo : MsiRGBDeviceInfo
@ -21,6 +20,12 @@ namespace RGB.NET.Devices.Msi
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected MsiDeviceUpdateQueue DeviceUpdateQueue { get; set; }
#endregion
#region Constructors
@ -28,7 +33,7 @@ namespace RGB.NET.Devices.Msi
/// <summary>
/// Initializes a new instance of the <see cref="MsiRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by Msi for the device.</param>
/// <param name="info">The generic information provided by MSI for the device.</param>
protected MsiRGBDevice(TDeviceInfo info)
{
this.DeviceInfo = info;
@ -41,9 +46,11 @@ namespace RGB.NET.Devices.Msi
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize()
public void Initialize(MsiDeviceUpdateQueue updateQueue, int ledCount)
{
InitializeLayout();
DeviceUpdateQueue = updateQueue;
InitializeLayout(ledCount);
if (Size == Size.Invalid)
{
@ -55,20 +62,11 @@ namespace RGB.NET.Devices.Msi
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
protected abstract void InitializeLayout(int ledCount);
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate)
{
List<Led> leds = ledsToUpdate.Where(x => x.Color.A > 0).ToList();
if (leds.Count > 0)
{
string deviceType = DeviceInfo.MsiDeviceType;
foreach (Led led in leds)
_MsiSDK.SetLedColor(deviceType, (int)led.CustomData, led.Color.GetR(), led.Color.GetG(), led.Color.GetB());
}
}
=> DeviceUpdateQueue.SetData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is int)));
#endregion
}

View File

@ -5,7 +5,7 @@ namespace RGB.NET.Devices.Msi
{
/// <inheritdoc />
/// <summary>
/// Represents a generic information for a Corsair-<see cref="T:RGB.NET.Core.IRGBDevice" />.
/// Represents a generic information for a MSI-<see cref="T:RGB.NET.Core.IRGBDevice" />.
/// </summary>
public class MsiRGBDeviceInfo : IRGBDeviceInfo
{

View File

@ -0,0 +1,56 @@
using RGB.NET.Core;
using RGB.NET.Devices.Msi.Native;
namespace RGB.NET.Devices.Msi
{
/// <inheritdoc />
/// <summary>
/// Represents MSI VGA adapters.
/// </summary>
public class MsiGraphicsCardRGBDevice : MsiRGBDevice<MsiRGBDeviceInfo>
{
#region Constructors
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiGraphicsCardRGBDevice" /> class.
/// </summary>
/// <param name="info">The specific information provided by MSI for graphics cards.</param>
internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info)
: base(info)
{ }
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout(int ledCount)
{
for (int i = 0; i < ledCount; i++)
{
//Hex3l: Should it be configurable in order to provide style access?
//Hex3l: Sets led style to "Steady" in order to have a solid color output therefore a controllable led color
//Hex3l: This is a string defined by the output of _MsiSDK.GetLedStyle, "Steady" should be always present
const string LED_STYLE = "Steady";
//Hex3l: Every led is a video card adapter.
_MsiSDK.SetLedStyle(DeviceInfo.MsiDeviceType, i, LED_STYLE);
InitializeLed(LedId.GraphicsCard1 + i, new Rectangle(i * 10, 0, 10, 10));
}
//TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images?
ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\MSI\GraphicsCard\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null);
}
/// <inheritdoc />
protected override object CreateLedCustomData(LedId ledId) => (int)ledId - (int)LedId.GraphicsCard1;
/// <inheritdoc />
public override void SyncBack()
{ }
#endregion
}
}

View File

@ -0,0 +1,54 @@
using RGB.NET.Core;
using RGB.NET.Devices.Msi.Native;
namespace RGB.NET.Devices.Msi
{
/// <inheritdoc />
/// <summary>
/// Represents a MSI mainboard.
/// </summary>
public class MsiMainboardRGBDevice : MsiRGBDevice<MsiRGBDeviceInfo>
{
#region Constructors
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiMainboardRGBDevice" /> class.
/// </summary>
/// <param name="info">The specific information provided by MSI for the mainboard.</param>
internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info)
: base(info)
{ }
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout(int ledCount)
{
for (int i = 0; i < ledCount; i++)
{
//Hex3l: Should it be configurable in order to provide style access?
//Hex3l: Sets led style to "Steady" in order to have a solid color output therefore a controllable led color
//Hex3l: This is a string defined by the output of _MsiSDK.GetLedStyle, "Steady" should be always present
const string LED_STYLE = "Steady";
_MsiSDK.SetLedStyle(DeviceInfo.MsiDeviceType, i, LED_STYLE);
InitializeLed(LedId.Mainboard1 + i, new Rectangle(i * 40, 0, 40, 8));
}
//TODO DarthAffe 07.10.2017: We don't know the model, how to save layouts and images?
ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\MSI\Mainboards\{DeviceInfo.Model.Replace(" ", string.Empty).ToUpper()}.xml"), null);
}
/// <inheritdoc />
protected override object CreateLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mainboard1;
/// <inheritdoc />
public override void SyncBack()
{ }
#endregion
}
}

View File

@ -13,7 +13,7 @@ namespace RGB.NET.Devices.Msi
{
/// <inheritdoc />
/// <summary>
/// Represents a device provider responsible for Cooler Master devices.
/// Represents a device provider responsible for MSI devices.
/// </summary>
public class MsiDeviceProvider : IRGBDeviceProvider
{
@ -62,6 +62,11 @@ namespace RGB.NET.Devices.Msi
/// </summary>
public Func<CultureInfo> GetCulture { get; set; } = CultureHelper.GetCurrentCulture;
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for corsair devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion
#region Constructors
@ -74,6 +79,8 @@ namespace RGB.NET.Devices.Msi
{
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(MsiDeviceProvider)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
}
#endregion
@ -87,6 +94,8 @@ namespace RGB.NET.Devices.Msi
try
{
UpdateTrigger?.Stop();
_MsiSDK.Reload();
IList<IRGBDevice> devices = new List<IRGBDevice>();
@ -102,11 +111,35 @@ namespace RGB.NET.Devices.Msi
{
try
{
//TODO DarthAffe 11.11.2017: What is this deviceType? Find someone to try that out
string deviceType = deviceTypes[i];
int ledCount = ledCounts[i];
//Hex3l: MSI_MB provide access to the motherboard "leds" where a led must be intended as a led header (JRGB, JRAINBOW etc..) (Tested on MSI X570 Unify)
if (deviceType.Equals("MSI_MB"))
{
MsiDeviceUpdateQueue updateQueue = new MsiDeviceUpdateQueue(UpdateTrigger, deviceType);
IMsiRGBDevice motherboard = new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "Msi", "Motherboard"));
motherboard.Initialize(updateQueue, ledCount);
devices.Add(motherboard);
}
else if (deviceType.Equals("MSI_VGA"))
{
//Hex3l: Every led under MSI_VGA should be a different graphics card. Handling all the cards together seems a good way to avoid overlapping of leds
//Hex3l: The led name is the name of the card (e.g. NVIDIA GeForce RTX 2080 Ti) we could provide it in device info.
MsiDeviceUpdateQueue updateQueue = new MsiDeviceUpdateQueue(UpdateTrigger, deviceType);
IMsiRGBDevice graphicscard = new MsiGraphicsCardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.GraphicsCard, deviceType, "Msi", "GraphicsCard"));
graphicscard.Initialize(updateQueue, ledCount);
devices.Add(graphicscard);
}
//TODO DarthAffe 22.02.2020: Add other devices
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger?.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}

View File

@ -3,7 +3,7 @@
namespace RGB.NET.Devices.Msi
{
/// <summary>
/// Represents a device provider loaded used to dynamically load msi devices into an application.
/// Represents a device provider loaded used to dynamically load MSI devices into an application.
/// </summary>
public class MsiDeviceProviderLoader : IRGBDeviceProviderLoader
{

View File

@ -110,51 +110,104 @@ namespace RGB.NET.Devices.Msi.Native
private delegate int InitializePointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetDeviceInfoPointer(out string[] pDevType, out int[] pLedCount);
private delegate int GetDeviceInfoPointer(
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pDevType,
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pLedCount);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedInfoPointer(string type, int index, out string pName, out string[] pLedStyles);
private delegate int GetLedInfoPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.BStr)] out string pName,
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pLedStyles);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedColorPointer(string type, int index, out int r, out int g, out int b);
private delegate int GetLedColorPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int r,
[Out, MarshalAs(UnmanagedType.I4)] out int g,
[Out, MarshalAs(UnmanagedType.I4)] out int b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedStylePointer(string type, int index, out int style);
private delegate int GetLedStylePointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.BStr)] out string style);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedMaxBrightPointer(string type, int index, out int maxLevel);
private delegate int GetLedMaxBrightPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int maxLevel);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedBrightPointer(string type, int index, out int currentLevel);
private delegate int GetLedBrightPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int currentLevel);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedMaxSpeedPointer(string type, int index, out int maxSpeed);
private delegate int GetLedMaxSpeedPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int maxSpeed);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetLedSpeedPointer(string type, int index, out int currentSpeed);
private delegate int GetLedSpeedPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[Out, MarshalAs(UnmanagedType.I4)] out int currentSpeed);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedColorPointer(string type, int index, int r, int g, int b);
private delegate int SetLedColorPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.I4)] int r,
[In, MarshalAs(UnmanagedType.I4)] int g,
[In, MarshalAs(UnmanagedType.I4)] int b);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedStylePointer(string type, int index, string style);
private delegate int SetLedStylePointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.BStr)] string style);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedBrightPointer(string type, int index, int level);
private delegate int SetLedBrightPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.I4)] int level);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int SetLedSpeedPointer(string type, int index, int speed);
private delegate int SetLedSpeedPointer(
[In, MarshalAs(UnmanagedType.BStr)] string type,
[In, MarshalAs(UnmanagedType.I4)] int index,
[In, MarshalAs(UnmanagedType.I4)] int speed);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetErrorMessagePointer(int errorCode, out string pDesc);
private delegate int GetErrorMessagePointer(
[In, MarshalAs(UnmanagedType.I4)] int errorCode,
[Out, MarshalAs(UnmanagedType.BStr)] out string pDesc);
#endregion
internal static int Initialize() => _initializePointer();
internal static int GetDeviceInfo(out string[] pDevType, out int[] pLedCount) => _getDeviceInfoPointer(out pDevType, out pLedCount);
internal static int GetDeviceInfo(out string[] pDevType, out int[] pLedCount)
{
// HACK - SDK GetDeviceInfo returns a string[] for ledCount, so we'll parse that to int.
int result = _getDeviceInfoPointer(out pDevType, out string[] ledCount);
pLedCount = new int[ledCount.Length];
for (int i = 0; i < ledCount.Length; i++)
pLedCount[i] = int.Parse(ledCount[i]);
return result;
}
internal static int GetLedInfo(string type, int index, out string pName, out string[] pLedStyles) => _getLedInfoPointer(type, index, out pName, out pLedStyles);
internal static int GetLedColor(string type, int index, out int r, out int g, out int b) => _getLedColorPointer(type, index, out r, out g, out b);
internal static int GetLedStyle(string type, int index, out int style) => _getLedStylePointer(type, index, out style);
internal static int GetLedStyle(string type, int index, out string style) => _getLedStylePointer(type, index, out style);
internal static int GetLedMaxBright(string type, int index, out int maxLevel) => _getLedMaxBrightPointer(type, index, out maxLevel);
internal static int GetLedBright(string type, int index, out int currentLevel) => _getLedBrightPointer(type, index, out currentLevel);
internal static int GetLedMaxSpeed(string type, int index, out int maxSpeed) => _getLedMaxSpeedPointer(type, index, out maxSpeed);

View File

@ -1,3 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enum/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generic/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=graphicscard/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mainboard/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>