mirror of
https://github.com/DarthAffe/RGB.NET.git
synced 2025-12-12 17:48:31 +00:00
Added SteelSeries-Support
This commit is contained in:
parent
afbc25e1b2
commit
65a291500b
10
RGB.NET.Devices.SteelSeries/API/Model/CoreProps.cs
Normal file
10
RGB.NET.Devices.SteelSeries/API/Model/CoreProps.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class CoreProps
|
||||
{
|
||||
[JsonProperty(PropertyName = "address")]
|
||||
public string Address { get; set; }
|
||||
}
|
||||
}
|
||||
34
RGB.NET.Devices.SteelSeries/API/Model/Event.cs
Normal file
34
RGB.NET.Devices.SteelSeries/API/Model/Event.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class Event
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
[JsonProperty("game")]
|
||||
public string Game { get; set; }
|
||||
|
||||
[JsonProperty("event")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("data")]
|
||||
public Dictionary<string, object> Data { get; } = new Dictionary<string, object>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Event()
|
||||
{ }
|
||||
|
||||
public Event(Game game, string name)
|
||||
{
|
||||
this.Name = name;
|
||||
Game = game.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
30
RGB.NET.Devices.SteelSeries/API/Model/Game.cs
Normal file
30
RGB.NET.Devices.SteelSeries/API/Model/Game.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class Game
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
[JsonProperty("game")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("game_display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Game()
|
||||
{ }
|
||||
|
||||
public Game(string name, string displayName)
|
||||
{
|
||||
Name = name;
|
||||
DisplayName = displayName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
30
RGB.NET.Devices.SteelSeries/API/Model/GoLispHandler.cs
Normal file
30
RGB.NET.Devices.SteelSeries/API/Model/GoLispHandler.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API.Model
|
||||
{
|
||||
internal class GoLispHandler
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
[JsonProperty("game")]
|
||||
public string Game { get; set; }
|
||||
|
||||
[JsonProperty("golisp")]
|
||||
public string Handler { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public GoLispHandler()
|
||||
{ }
|
||||
|
||||
public GoLispHandler(Game game, string handler)
|
||||
{
|
||||
this.Handler = handler;
|
||||
Game = game.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
120
RGB.NET.Devices.SteelSeries/API/SteelSeriesSDK.cs
Normal file
120
RGB.NET.Devices.SteelSeries/API/SteelSeriesSDK.cs
Normal file
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using RGB.NET.Devices.SteelSeries.API.Model;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.API
|
||||
{
|
||||
internal static class SteelSeriesSDK
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string GAME_NAME = "RGBNET";
|
||||
private const string GAME_DISPLAYNAME = "RGB.NET";
|
||||
private const string EVENT_NAME = "UPDATELEDS";
|
||||
private const string HANDLER = @"(handler """ + EVENT_NAME + @"""
|
||||
(lambda (data)
|
||||
(let* ((device (value: data))
|
||||
(zoneData (frame: data))
|
||||
(zones (frame-keys zoneData)))
|
||||
(do ((zoneDo zones (cdr zoneDo)))
|
||||
((nil? zoneDo))
|
||||
(let* ((zone (car zoneDo))
|
||||
(color (get-slot zoneData zone)))
|
||||
(on-device device show-on-zone: color zone))))))";
|
||||
|
||||
private const string CORE_PROPS_WINDOWS = "%PROGRAMDATA%/SteelSeries/SteelSeries Engine 3/coreProps.json";
|
||||
private const string CORE_PROPS_OSX = "/Library/Application Support/SteelSeries Engine 3/coreProps.json";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
private static readonly HttpClient _client = new HttpClient();
|
||||
private static readonly Game _game = new Game(GAME_NAME, GAME_DISPLAYNAME);
|
||||
private static readonly Event _event = new Event(_game, EVENT_NAME);
|
||||
private static string _baseUrl;
|
||||
|
||||
internal static bool IsInitialized => !string.IsNullOrWhiteSpace(_baseUrl);
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal static bool Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
string corePropsPath = GetCorePropsPath();
|
||||
if (!string.IsNullOrWhiteSpace(corePropsPath) && File.Exists(corePropsPath))
|
||||
{
|
||||
CoreProps coreProps = JsonConvert.DeserializeObject<CoreProps>(File.ReadAllText(corePropsPath));
|
||||
_baseUrl = coreProps.Address;
|
||||
if (!_baseUrl.StartsWith("http://", StringComparison.Ordinal))
|
||||
_baseUrl = "http://" + _baseUrl;
|
||||
|
||||
RegisterGame(_game);
|
||||
RegisterGoLispHandler(new GoLispHandler(_game, HANDLER));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
_baseUrl = null;
|
||||
}
|
||||
return IsInitialized;
|
||||
}
|
||||
|
||||
internal static void UpdateLeds(string device, Dictionary<string, int[]> data)
|
||||
{
|
||||
_event.Data.Clear();
|
||||
_event.Data.Add("value", device);
|
||||
_event.Data.Add("frame", data);
|
||||
|
||||
TriggerEvent(_event);
|
||||
}
|
||||
|
||||
internal static void SendHeartbeat() => SendHeartbeat(_game);
|
||||
|
||||
internal static void ResetLeds() => StopGame(_game);
|
||||
|
||||
internal static void Dispose()
|
||||
{
|
||||
ResetLeds();
|
||||
_client.Dispose();
|
||||
}
|
||||
|
||||
private static string TriggerEvent(Event e) => PostJson("/game_event", e);
|
||||
private static string RegisterGoLispHandler(GoLispHandler handler) => PostJson("/load_golisp_handlers", handler);
|
||||
private static string RegisterEvent(Event e) => PostJson("/register_game_event", e);
|
||||
private static string UnregisterEvent(Event e) => PostJson("/remove_game_event", e);
|
||||
private static string RegisterGame(Game game) => PostJson("/game_metadata", game);
|
||||
private static string UnregisterGame(Game game) => PostJson("/remove_game", game);
|
||||
private static string StopGame(Game game) => PostJson("/stop_game", game);
|
||||
private static string SendHeartbeat(Game game) => PostJson("/game_heartbeat", game);
|
||||
|
||||
private static string PostJson(string urlSuffix, object o)
|
||||
{
|
||||
string payload = JsonConvert.SerializeObject(o);
|
||||
return _client.PostAsync(_baseUrl + urlSuffix, new StringContent(payload, Encoding.UTF8, "application/json")).Result.Content.ReadAsStringAsync().Result;
|
||||
}
|
||||
|
||||
private static string GetCorePropsPath()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
return Environment.ExpandEnvironmentVariables(CORE_PROPS_WINDOWS);
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
return CORE_PROPS_OSX;
|
||||
|
||||
throw new InvalidOperationException("Unknown operating system.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
20
RGB.NET.Devices.SteelSeries/Attribute/APIName.cs
Normal file
20
RGB.NET.Devices.SteelSeries/Attribute/APIName.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
internal class APIName : System.Attribute
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public APIName(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
internal static class SteelSeriesEnumExtension
|
||||
{
|
||||
#region Properties & Fields
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
private static readonly Dictionary<SteelSeriesDeviceType, string> _deviceTypeNames = new Dictionary<SteelSeriesDeviceType, string>();
|
||||
private static readonly Dictionary<SteelSeriesLedId, string> _ledIdNames = new Dictionary<SteelSeriesLedId, string>();
|
||||
|
||||
// ReSharper restore InconsistentNaming
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal static string GetAPIName(this SteelSeriesDeviceType deviceType)
|
||||
{
|
||||
if (!_deviceTypeNames.TryGetValue(deviceType, out string apiName))
|
||||
_deviceTypeNames.Add(deviceType, apiName = GetAPIName(typeof(SteelSeriesDeviceType), deviceType));
|
||||
|
||||
return apiName;
|
||||
}
|
||||
|
||||
internal static string GetAPIName(this SteelSeriesLedId ledId)
|
||||
{
|
||||
if (!_ledIdNames.TryGetValue(ledId, out string apiName))
|
||||
_ledIdNames.Add(ledId, apiName = GetAPIName(typeof(SteelSeriesLedId), ledId));
|
||||
|
||||
return apiName;
|
||||
}
|
||||
|
||||
private static string GetAPIName(Type type, Enum value)
|
||||
{
|
||||
MemberInfo[] memInfo = type.GetMember(value.ToString());
|
||||
if (memInfo.Length == 0) return null;
|
||||
return (memInfo.FirstOrDefault()?.GetCustomAttributes(typeof(APIName), false).FirstOrDefault() as APIName)?.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
23
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs
Normal file
23
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesDeviceType.cs
Normal file
@ -0,0 +1,23 @@
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
public enum SteelSeriesDeviceType
|
||||
{
|
||||
[APIName("rgb-per-key-zones")]
|
||||
PerKey,
|
||||
|
||||
[APIName("rgb-1-zone")]
|
||||
OneZone,
|
||||
|
||||
[APIName("rgb-2-zone")]
|
||||
TwoZone,
|
||||
|
||||
[APIName("rgb-3-zone")]
|
||||
ThreeZone,
|
||||
|
||||
[APIName("rgb-4-zone")]
|
||||
FourZone,
|
||||
|
||||
[APIName("rgb-5-zone")]
|
||||
FiveZone
|
||||
}
|
||||
}
|
||||
243
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs
Normal file
243
RGB.NET.Devices.SteelSeries/Enum/SteelSeriesLedId.cs
Normal file
@ -0,0 +1,243 @@
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
public enum SteelSeriesLedId
|
||||
{
|
||||
[APIName("one")]
|
||||
ZoneOne,
|
||||
[APIName("two")]
|
||||
ZoneTwo,
|
||||
[APIName("three")]
|
||||
ZoneThree,
|
||||
[APIName("four")]
|
||||
ZoneFour,
|
||||
[APIName("five")]
|
||||
ZoneFive,
|
||||
|
||||
[APIName("logo")]
|
||||
Logo,
|
||||
[APIName("a")]
|
||||
A,
|
||||
[APIName("b")]
|
||||
B,
|
||||
[APIName("c")]
|
||||
C,
|
||||
[APIName("d")]
|
||||
D,
|
||||
[APIName("e")]
|
||||
E,
|
||||
[APIName("f")]
|
||||
F,
|
||||
[APIName("g")]
|
||||
G,
|
||||
[APIName("h")]
|
||||
H,
|
||||
[APIName("i")]
|
||||
I,
|
||||
[APIName("j")]
|
||||
J,
|
||||
[APIName("k")]
|
||||
K,
|
||||
[APIName("l")]
|
||||
L,
|
||||
[APIName("m")]
|
||||
M,
|
||||
[APIName("n")]
|
||||
N,
|
||||
[APIName("o")]
|
||||
O,
|
||||
[APIName("p")]
|
||||
P,
|
||||
[APIName("q")]
|
||||
Q,
|
||||
[APIName("r")]
|
||||
R,
|
||||
[APIName("s")]
|
||||
S,
|
||||
[APIName("t")]
|
||||
T,
|
||||
[APIName("u")]
|
||||
U,
|
||||
[APIName("v")]
|
||||
V,
|
||||
[APIName("w")]
|
||||
W,
|
||||
[APIName("x")]
|
||||
X,
|
||||
[APIName("y")]
|
||||
Y,
|
||||
[APIName("z")]
|
||||
Z,
|
||||
[APIName("keyboard-1")]
|
||||
Keyboard1,
|
||||
[APIName("keyboard-2")]
|
||||
Keyboard2,
|
||||
[APIName("keyboard-3")]
|
||||
Keyboard3,
|
||||
[APIName("keyboard-4")]
|
||||
Keyboard4,
|
||||
[APIName("keyboard-5")]
|
||||
Keyboard5,
|
||||
[APIName("keyboard-6")]
|
||||
Keyboard6,
|
||||
[APIName("keyboard-7")]
|
||||
Keyboard7,
|
||||
[APIName("keyboard-8")]
|
||||
Keyboard8,
|
||||
[APIName("keyboard-9")]
|
||||
Keyboard9,
|
||||
[APIName("keyboard-0")]
|
||||
Keyboard0,
|
||||
[APIName("return")]
|
||||
Return,
|
||||
[APIName("escape")]
|
||||
Escape,
|
||||
[APIName("backspace")]
|
||||
Backspace,
|
||||
[APIName("tab")]
|
||||
Tab,
|
||||
[APIName("spacebar")]
|
||||
Spacebar,
|
||||
[APIName("caps")]
|
||||
Caps,
|
||||
[APIName("dash")]
|
||||
Dash,
|
||||
[APIName("equal")]
|
||||
Equal,
|
||||
[APIName("l-bracket")]
|
||||
LBracket,
|
||||
[APIName("r-bracket")]
|
||||
RBracket,
|
||||
[APIName("backslash")]
|
||||
Backslash,
|
||||
[APIName("pound")]
|
||||
Pound,
|
||||
[APIName("semicolon")]
|
||||
Semicolon,
|
||||
[APIName("quote")]
|
||||
Quote,
|
||||
[APIName("backquote")]
|
||||
Backqoute,
|
||||
[APIName("comma")]
|
||||
Comma,
|
||||
[APIName("period")]
|
||||
Period,
|
||||
[APIName("slash")]
|
||||
Slash,
|
||||
[APIName("f1")]
|
||||
F1,
|
||||
[APIName("f2")]
|
||||
F2,
|
||||
[APIName("f3")]
|
||||
F3,
|
||||
[APIName("f4")]
|
||||
F4,
|
||||
[APIName("f5")]
|
||||
F5,
|
||||
[APIName("f6")]
|
||||
F6,
|
||||
[APIName("f7")]
|
||||
F7,
|
||||
[APIName("f8")]
|
||||
F8,
|
||||
[APIName("f9")]
|
||||
F9,
|
||||
[APIName("f10")]
|
||||
F10,
|
||||
[APIName("f11")]
|
||||
F11,
|
||||
[APIName("f12")]
|
||||
F12,
|
||||
[APIName("printscreen")]
|
||||
PrintScreen,
|
||||
[APIName("scrolllock")]
|
||||
ScrollLock,
|
||||
[APIName("pause")]
|
||||
Pause,
|
||||
[APIName("insert")]
|
||||
Insert,
|
||||
[APIName("home")]
|
||||
Home,
|
||||
[APIName("pageup")]
|
||||
PageUp,
|
||||
[APIName("delete")]
|
||||
Delete,
|
||||
[APIName("end")]
|
||||
End,
|
||||
[APIName("pagedown")]
|
||||
PageDown,
|
||||
[APIName("rightarrow")]
|
||||
RightArrow,
|
||||
[APIName("leftarrow")]
|
||||
LeftArrow,
|
||||
[APIName("downarrow")]
|
||||
DownArrow,
|
||||
[APIName("uparrow")]
|
||||
UpArrow,
|
||||
[APIName("keypad-num-lock")]
|
||||
KeypadNumLock,
|
||||
[APIName("keypad-divide")]
|
||||
KeypadDivide,
|
||||
[APIName("keypad-times")]
|
||||
KeypadTimes,
|
||||
[APIName("keypad-minus")]
|
||||
KeypadMinus,
|
||||
[APIName("keypad-plus")]
|
||||
KeypadPlus,
|
||||
[APIName("keypad-enter")]
|
||||
KeypadEnter,
|
||||
[APIName("keypad-period")]
|
||||
KeypadPeriod,
|
||||
[APIName("keypad-1")]
|
||||
Keypad1,
|
||||
[APIName("keypad-2")]
|
||||
Keypad2,
|
||||
[APIName("keypad-3")]
|
||||
Keypad3,
|
||||
[APIName("keypad-4")]
|
||||
Keypad4,
|
||||
[APIName("keypad-5")]
|
||||
Keypad5,
|
||||
[APIName("keypad-6")]
|
||||
Keypad6,
|
||||
[APIName("keypad-7")]
|
||||
Keypad7,
|
||||
[APIName("keypad-8")]
|
||||
Keypad8,
|
||||
[APIName("keypad-9")]
|
||||
Keypad9,
|
||||
[APIName("keypad-0")]
|
||||
Keypad0,
|
||||
[APIName("l-ctrl")]
|
||||
LCtrl,
|
||||
[APIName("l-shift")]
|
||||
LShift,
|
||||
[APIName("l-alt")]
|
||||
LAlt,
|
||||
[APIName("l-win")]
|
||||
LWin,
|
||||
[APIName("r-ctrl")]
|
||||
RCtrl,
|
||||
[APIName("r-shift")]
|
||||
RShift,
|
||||
[APIName("r-alt")]
|
||||
RAlt,
|
||||
[APIName("r-win")]
|
||||
RWin,
|
||||
[APIName("ss-key")]
|
||||
SSKey,
|
||||
[APIName("win-menu")]
|
||||
WinMenu,
|
||||
[APIName("m0")]
|
||||
M0,
|
||||
[APIName("m1")]
|
||||
M1,
|
||||
[APIName("m2")]
|
||||
M2,
|
||||
[APIName("m3")]
|
||||
M3,
|
||||
[APIName("m4")]
|
||||
M4,
|
||||
[APIName("m5")]
|
||||
M5,
|
||||
}
|
||||
}
|
||||
13
RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs
Normal file
13
RGB.NET.Devices.SteelSeries/Generic/ISteelSeriesRGBDevice.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a steelseries RGB-device.
|
||||
/// </summary>
|
||||
internal interface ISteelSeriesRGBDevice : IRGBDevice
|
||||
{
|
||||
void Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Devices.SteelSeries.API;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents the update-queue performing updates for steelseries devices.
|
||||
/// </summary>
|
||||
internal class SteelSeriesDeviceUpdateQueue : UpdateQueue
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private string _deviceType;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SteelSeriesDeviceUpdateQueue"/> 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 SteelSeriesDeviceUpdateQueue(IDeviceUpdateTrigger updateTrigger, string deviceType)
|
||||
: base(updateTrigger)
|
||||
{
|
||||
this._deviceType = deviceType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Update(Dictionary<object, Color> dataSet)
|
||||
{
|
||||
SteelSeriesSDK.UpdateLeds(_deviceType, dataSet.ToDictionary(x => ((SteelSeriesLedId)x.Key).GetAPIName(), x => new int[] { x.Value.R, x.Value.G, x.Value.B }));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
88
RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs
Normal file
88
RGB.NET.Devices.SteelSeries/Generic/SteelSeriesRGBDevice.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
|
||||
/// <inheritdoc cref="ISteelSeriesRGBDevice" />
|
||||
/// <summary>
|
||||
/// Represents a SteelSeries-device. (keyboard, mouse, headset, mousepad).
|
||||
/// </summary>
|
||||
public class SteelSeriesRGBDevice : AbstractRGBDevice<SteelSeriesRGBDeviceInfo>, ISteelSeriesRGBDevice
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private Dictionary<LedId, SteelSeriesLedId> _ledMapping;
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets information about the <see cref="SteelSeriesRGBDevice" />.
|
||||
/// </summary>
|
||||
public override SteelSeriesRGBDeviceInfo DeviceInfo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the update queue performing updates for this device.
|
||||
/// </summary>
|
||||
// ReSharper disable once MemberCanBePrivate.Global
|
||||
protected UpdateQueue UpdateQueue { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SteelSeriesRGBDevice"/> class.
|
||||
/// </summary>
|
||||
/// <param name="info">The generic information provided by SteelSeries for the device.</param>
|
||||
internal SteelSeriesRGBDevice(SteelSeriesRGBDeviceInfo info)
|
||||
{
|
||||
this.DeviceInfo = info;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the device.
|
||||
/// </summary>
|
||||
void ISteelSeriesRGBDevice.Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping)
|
||||
{
|
||||
_ledMapping = ledMapping;
|
||||
|
||||
int counter = 0;
|
||||
foreach (KeyValuePair<LedId, SteelSeriesLedId> mapping in ledMapping)
|
||||
InitializeLed(mapping.Key, new Rectangle((counter++) * 10, 0, 10, 10));
|
||||
|
||||
InitializeLayout();
|
||||
|
||||
if (Size == Size.Invalid)
|
||||
{
|
||||
Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle));
|
||||
Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
|
||||
}
|
||||
|
||||
UpdateQueue = updateQueue;
|
||||
}
|
||||
|
||||
protected override object CreateLedCustomData(LedId ledId) => _ledMapping[ledId];
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0));
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
|
||||
/// </summary>
|
||||
protected virtual void InitializeLayout()
|
||||
{
|
||||
if (!(DeviceInfo is SteelSeriesRGBDeviceInfo info)) return;
|
||||
|
||||
string layout = info.ImageLayout;
|
||||
string layoutPath = info.LayoutPath;
|
||||
ApplyLayoutFromFile(PathHelper.GetAbsolutePath($@"Layouts\SteelSeries\{layoutPath}.xml"), layout, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a generic information for a SteelSeries-<see cref="T:RGB.NET.Core.IRGBDevice" />.
|
||||
/// </summary>
|
||||
public class SteelSeriesRGBDeviceInfo : IRGBDeviceInfo
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public RGBDeviceType DeviceType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DeviceName { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Manufacturer => "SteelSeries";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Model { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public Uri Image { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool SupportsSyncBack => false;
|
||||
|
||||
public SteelSeriesDeviceType SteelSeriesDeviceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the layout used to decide which images to load.
|
||||
/// </summary>
|
||||
internal string ImageLayout { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path/name of the layout-file.
|
||||
/// </summary>
|
||||
internal string LayoutPath { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Internal constructor of managed <see cref="SteelSeriesRGBDeviceInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="deviceType">The type of the <see cref="IRGBDevice"/>.</param>
|
||||
/// <param name="model">The represented device model.</param>
|
||||
/// <param name="deviceCaps">The lighting-capabilities of the device.</param>
|
||||
/// <param name="imageLayout">The layout used to decide which images to load.</param>
|
||||
/// <param name="layoutPath">The path/name of the layout-file.</param>
|
||||
internal SteelSeriesRGBDeviceInfo(RGBDeviceType deviceType, string model, SteelSeriesDeviceType steelSeriesDeviceType, string imageLayout, string layoutPath)
|
||||
{
|
||||
this.DeviceType = deviceType;
|
||||
this.Model = model;
|
||||
this.SteelSeriesDeviceType = steelSeriesDeviceType;
|
||||
this.ImageLayout = imageLayout;
|
||||
this.LayoutPath = layoutPath;
|
||||
|
||||
DeviceName = $"{Manufacturer} {Model}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
47
RGB.NET.Devices.SteelSeries/HID/DeviceChecker.cs
Normal file
47
RGB.NET.Devices.SteelSeries/HID/DeviceChecker.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HidSharp;
|
||||
using RGB.NET.Core;
|
||||
using DeviceDataList = System.Collections.Generic.List<(string model, RGB.NET.Core.RGBDeviceType deviceType, int id, RGB.NET.Devices.SteelSeries.SteelSeriesDeviceType steelSeriesDeviceType, string imageLayout, string layoutPath, System.Collections.Generic.Dictionary<RGB.NET.Core.LedId, RGB.NET.Devices.SteelSeries.SteelSeriesLedId> ledMapping)>;
|
||||
using LedMapping = System.Collections.Generic.Dictionary<RGB.NET.Core.LedId, RGB.NET.Devices.SteelSeries.SteelSeriesLedId>;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries.HID
|
||||
{
|
||||
internal static class DeviceChecker
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const int VENDOR_ID = 0x1038;
|
||||
|
||||
//TODO DarthAffe 16.02.2019: Add devices
|
||||
private static readonly DeviceDataList DEVICES = new DeviceDataList
|
||||
{
|
||||
("Rival 500", RGBDeviceType.Mouse, 0x170E, SteelSeriesDeviceType.TwoZone, "default", @"Mice\Rival500", new LedMapping { { LedId.Mouse1, SteelSeriesLedId.ZoneOne},
|
||||
{ LedId.Mouse2, SteelSeriesLedId.ZoneTwo} }),
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
public static DeviceDataList ConnectedDevices { get; } = new DeviceDataList();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal static void LoadDeviceList(RGBDeviceType loadFilter)
|
||||
{
|
||||
ConnectedDevices.Clear();
|
||||
|
||||
HashSet<int> ids = new HashSet<int>(DeviceList.Local.GetHidDevices(VENDOR_ID).Select(x => x.ProductID).Distinct());
|
||||
DeviceDataList connectedDevices = DEVICES.Where(d => ids.Contains(d.id) && loadFilter.HasFlag(d.deviceType)).ToList();
|
||||
|
||||
List<SteelSeriesDeviceType> connectedDeviceTypes = connectedDevices.Select(d => d.steelSeriesDeviceType).ToList();
|
||||
foreach (SteelSeriesDeviceType deviceType in connectedDeviceTypes)
|
||||
ConnectedDevices.Add(connectedDevices.Where(d => d.steelSeriesDeviceType == deviceType).OrderByDescending(d => d.ledMapping.Count).First());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
|
||||
|
||||
<Authors>Darth Affe</Authors>
|
||||
<Company>Wyrez</Company>
|
||||
<Language>en-US</Language>
|
||||
<NeutralLanguage>en-US</NeutralLanguage>
|
||||
<Title>RGB.NET.Devices.SteelSeries</Title>
|
||||
<AssemblyName>RGB.NET.Devices.SteelSeries</AssemblyName>
|
||||
<AssemblyTitle>RGB.NET.Devices.SteelSeries</AssemblyTitle>
|
||||
<PackageId>RGB.NET.Devices.SteelSeries</PackageId>
|
||||
<RootNamespace>RGB.NET.Devices.SteelSeries</RootNamespace>
|
||||
<Description>SteelSeries-Device-Implementations of RGB.NET</Description>
|
||||
<Summary>SteelSeries-Device-Implementations of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals</Summary>
|
||||
<Copyright>Copyright © Wyrez 2017</Copyright>
|
||||
<PackageCopyright>Copyright © Wyrez 2017</PackageCopyright>
|
||||
<PackageIconUrl>http://lib.arge.be/icon.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/DarthAffe/RGB.NET</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE</PackageLicenseUrl>
|
||||
<RepositoryType>Github</RepositoryType>
|
||||
<RepositoryUrl>https://github.com/DarthAffe/RGB.NET</RepositoryUrl>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
|
||||
<PackageReleaseNotes></PackageReleaseNotes>
|
||||
|
||||
<Version>0.0.1</Version>
|
||||
<AssemblyVersion>0.0.1</AssemblyVersion>
|
||||
<FileVersion>0.0.1</FileVersion>
|
||||
|
||||
<OutputPath>..\bin\</OutputPath>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<IncludeSource>True</IncludeSource>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
|
||||
<DefineConstants>NETCORE;NETSTANDARD;NETSTANDARD2_0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DefineConstants>$(DefineConstants);TRACE;DEBUG</DefineConstants>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>$(NoWarn);CS1591;CS1572;CS1573</NoWarn>
|
||||
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RGB.NET.Core\RGB.NET.Core.csproj" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="HidSharp" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,4 @@
|
||||
<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/=attribute/@EntryIndexedValue">True</s:Boolean>
|
||||
<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>
|
||||
129
RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs
Normal file
129
RGB.NET.Devices.SteelSeries/SteelSeriesDeviceProvider.cs
Normal file
@ -0,0 +1,129 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Devices.SteelSeries.API;
|
||||
using RGB.NET.Devices.SteelSeries.HID;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Represents a device provider responsible for SteelSeries- devices.
|
||||
/// </summary>
|
||||
public class SteelSeriesDeviceProvider : IRGBDeviceProvider
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private static SteelSeriesDeviceProvider _instance;
|
||||
/// <summary>
|
||||
/// Gets the singleton <see cref="SteelSeriesDeviceProvider"/> instance.
|
||||
/// </summary>
|
||||
public static SteelSeriesDeviceProvider Instance => _instance ?? new SteelSeriesDeviceProvider();
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Indicates if the SDK is initialized and ready to use.
|
||||
/// </summary>
|
||||
public bool IsInitialized { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
/// <summary>
|
||||
/// Gets whether the application has exclusive access to the SDK or not.
|
||||
/// </summary>
|
||||
public bool HasExclusiveAccess => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IRGBDevice> Devices { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for SteelSeries devices.
|
||||
/// </summary>
|
||||
public DeviceUpdateTrigger UpdateTrigger { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SteelSeriesDeviceProvider"/> class.
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">Thrown if this constructor is called even if there is already an instance of this class.</exception>
|
||||
public SteelSeriesDeviceProvider()
|
||||
{
|
||||
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}");
|
||||
_instance = this;
|
||||
|
||||
UpdateTrigger = new DeviceUpdateTrigger();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsInitialized = false;
|
||||
|
||||
UpdateTrigger?.Stop();
|
||||
|
||||
if (!SteelSeriesSDK.IsInitialized)
|
||||
SteelSeriesSDK.Initialize();
|
||||
|
||||
IList<IRGBDevice> devices = new List<IRGBDevice>();
|
||||
DeviceChecker.LoadDeviceList(loadFilter);
|
||||
|
||||
try
|
||||
{
|
||||
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, string imageLayout, string layoutPath, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices)
|
||||
{
|
||||
ISteelSeriesRGBDevice device = new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType, imageLayout, layoutPath));
|
||||
SteelSeriesDeviceUpdateQueue updateQueue = new SteelSeriesDeviceUpdateQueue(UpdateTrigger, steelSeriesDeviceType.GetAPIName());
|
||||
device.Initialize(updateQueue, ledMapping);
|
||||
devices.Add(device);
|
||||
}
|
||||
}
|
||||
catch { if (throwExceptions) throw; }
|
||||
|
||||
UpdateTrigger?.Start();
|
||||
|
||||
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
|
||||
IsInitialized = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
IsInitialized = false;
|
||||
if (throwExceptions) throw;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ResetDevices()
|
||||
{
|
||||
if (IsInitialized)
|
||||
try
|
||||
{
|
||||
SteelSeriesSDK.ResetLeds();
|
||||
}
|
||||
catch {/* shit happens */}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
SteelSeriesSDK.Dispose();
|
||||
}
|
||||
catch {/* shit happens */}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace RGB.NET.Devices.SteelSeries
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a device provider loaded used to dynamically load steelseries devices into an application.
|
||||
/// </summary>
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
public class SteelSeriesDeviceProviderLoader : IRGBDeviceProviderLoader
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool RequiresInitialization => false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRGBDeviceProvider GetDeviceProvider() => SteelSeriesDeviceProvider.Instance;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -39,6 +39,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Groups", "RGB.NET.G
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.WS281X", "RGB.NET.Devices.WS281X\RGB.NET.Devices.WS281X.csproj", "{0AD382DA-E999-4F74-9658-8D402EE9BF3F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.SteelSeries", "RGB.NET.Devices.SteelSeries\RGB.NET.Devices.SteelSeries.csproj", "{FFDE4387-60F2-47B6-9704-3A57D02B8C64}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -109,6 +111,10 @@ Global
|
||||
{0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0AD382DA-E999-4F74-9658-8D402EE9BF3F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -129,6 +135,7 @@ Global
|
||||
{8725C448-818C-41F7-B23F-F97E062BF233} = {EBC33090-8494-4DF4-B4B6-64D0E531E93F}
|
||||
{6FEBDC9E-909D-4EE2-B003-EDFBEF5FFF40} = {EBC33090-8494-4DF4-B4B6-64D0E531E93F}
|
||||
{0AD382DA-E999-4F74-9658-8D402EE9BF3F} = {D13032C6-432E-4F43-8A32-071133C22B16}
|
||||
{FFDE4387-60F2-47B6-9704-3A57D02B8C64} = {D13032C6-432E-4F43-8A32-071133C22B16}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {7F222AD4-1F9E-4AAB-9D69-D62372D4C1BA}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user