From 4b2aba844732a549a5b4f6903c30923f4cafd91c Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Sun, 10 Jun 2018 22:01:03 +0200 Subject: [PATCH] Added SoIP device-provider (WIP) --- .../Client/SoIPClientDeviceDefinition.cs | 41 ++++++ .../Client/SoIPClientRGBDevice.cs | 87 +++++++++++ .../Client/SoIPClientRGBDeviceInfo.cs | 56 +++++++ RGB.NET.Devices.SoIP/FodyWeavers.xml | 4 + .../Generic/ISoIPDeviceDefinition.cs | 8 + .../Generic/ISoIPRGBDevice.cs | 11 ++ .../RGB.NET.Devices.SoIP.csproj | 74 ++++++++++ .../Server/SoIPServerDeviceDefinition.cs | 44 ++++++ .../Server/SoIPServerRGBDevice.cs | 76 ++++++++++ .../Server/SoIPServerRGBDeviceInfo.cs | 50 +++++++ .../Server/SoIPServerUpdateQueue.cs | 54 +++++++ RGB.NET.Devices.SoIP/SoIPDeviceProvider.cs | 139 ++++++++++++++++++ .../SoIPDeviceProviderLoader.cs | 24 +++ RGB.NET.sln | 12 ++ RGB.NET.sln.DotSettings | 1 + 15 files changed, 681 insertions(+) create mode 100644 RGB.NET.Devices.SoIP/Client/SoIPClientDeviceDefinition.cs create mode 100644 RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs create mode 100644 RGB.NET.Devices.SoIP/Client/SoIPClientRGBDeviceInfo.cs create mode 100644 RGB.NET.Devices.SoIP/FodyWeavers.xml create mode 100644 RGB.NET.Devices.SoIP/Generic/ISoIPDeviceDefinition.cs create mode 100644 RGB.NET.Devices.SoIP/Generic/ISoIPRGBDevice.cs create mode 100644 RGB.NET.Devices.SoIP/RGB.NET.Devices.SoIP.csproj create mode 100644 RGB.NET.Devices.SoIP/Server/SoIPServerDeviceDefinition.cs create mode 100644 RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs create mode 100644 RGB.NET.Devices.SoIP/Server/SoIPServerRGBDeviceInfo.cs create mode 100644 RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs create mode 100644 RGB.NET.Devices.SoIP/SoIPDeviceProvider.cs create mode 100644 RGB.NET.Devices.SoIP/SoIPDeviceProviderLoader.cs diff --git a/RGB.NET.Devices.SoIP/Client/SoIPClientDeviceDefinition.cs b/RGB.NET.Devices.SoIP/Client/SoIPClientDeviceDefinition.cs new file mode 100644 index 0000000..470df74 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Client/SoIPClientDeviceDefinition.cs @@ -0,0 +1,41 @@ +using RGB.NET.Devices.SoIP.Generic; + +namespace RGB.NET.Devices.SoIP.Client +{ + public class SoIPClientDeviceDefinition : ISoIPDeviceDefinition + { + #region Properties & Fields + + /// + /// Gets or sets the hostname of the device. + /// + public string Hostname { get; set; } + + /// + /// Gets or sets the port to device is listening to. + /// + public int Port { get; set; } + + /// + /// Gets or sets the manufacturer of the device. + /// + public string Manufacturer { get; set; } = "Unknown"; + + /// + /// Gets or sets the model name of the device. + /// + public string Model { get; set; } = "Generic SoIP-Device"; + + #endregion + + #region Constructors + + public SoIPClientDeviceDefinition(string hostname, int port) + { + this.Hostname = hostname; + this.Port = port; + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs b/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs new file mode 100644 index 0000000..0ba9697 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDevice.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RGB.NET.Core; +using RGB.NET.Devices.SoIP.Generic; +using SimpleTCP; + +namespace RGB.NET.Devices.SoIP.Client +{ + public class SoIPClientRGBDevice : AbstractRGBDevice, ISoIPRGBDevice + { + #region Properties & Fields + + private readonly Dictionary _syncbackCache = new Dictionary(); + private readonly SimpleTcpClient _tcpClient; + + public override SoIPClientRGBDeviceInfo DeviceInfo { get; } + + #endregion + + #region Constructors + + public SoIPClientRGBDevice(SoIPClientRGBDeviceInfo deviceInfo) + { + this.DeviceInfo = deviceInfo; + + _tcpClient = new SimpleTcpClient(); + _tcpClient.DelimiterDataReceived += TcpClientOnDelimiterDataReceived; + } + + #endregion + + #region Methods + + void ISoIPRGBDevice.Initialize(IDeviceUpdateTrigger updateTrigger) + { + _tcpClient.Connect(DeviceInfo.Hostname, DeviceInfo.Port); + } + + /// + protected override void UpdateLeds(IEnumerable ledsToUpdate) + { } + + /// + public override void SyncBack() + { + lock (_syncbackCache) + { + foreach (KeyValuePair cacheEntry in _syncbackCache) + { + LedId ledId = cacheEntry.Key; + Color color = cacheEntry.Value; + + if (!LedMapping.TryGetValue(ledId, out Led led)) + led = InitializeLed(cacheEntry.Key, new Rectangle(0, 0, 10, 10)); //TODO DarthAffe 10.06.2018: Send layout with initial package + + SetLedColorWithoutRequest(led, color); + } + + _syncbackCache.Clear(); + } + } + + private void TcpClientOnDelimiterDataReceived(object sender, Message message) + { + List<(LedId, Color)> leds = message.MessageString.Split(';').Select(x => + { + string[] led = x.Split('|'); + return ((LedId)Enum.Parse(typeof(LedId), led[0]), Color.FromHexString(led[1])); + }).ToList(); + lock (_syncbackCache) + foreach ((LedId ledId, Color color) in leds) + _syncbackCache[ledId] = color; + } + + /// + public override void Dispose() + { + base.Dispose(); + + _tcpClient.Disconnect(); + _tcpClient.Dispose(); + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDeviceInfo.cs b/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDeviceInfo.cs new file mode 100644 index 0000000..a878d09 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Client/SoIPClientRGBDeviceInfo.cs @@ -0,0 +1,56 @@ +using System; +using RGB.NET.Core; + +namespace RGB.NET.Devices.SoIP.Client +{ + /// + /// + /// Represents device information for a />. + /// + public class SoIPClientRGBDeviceInfo : IRGBDeviceInfo + { + #region Properties & Fields + + /// + public RGBDeviceType DeviceType => RGBDeviceType.Unknown; + + /// + public string Manufacturer { get; } + + /// + public string Model { get; } + + /// + public RGBDeviceLighting Lighting => RGBDeviceLighting.None; + + /// + public bool SupportsSyncBack => true; + + /// + public Uri Image { get; set; } + + /// + /// The hostname of the device. + /// + public string Hostname { get; } + + /// + /// The port of the device. + /// + public int Port { get; } + + #endregion + + #region Constructors + + internal SoIPClientRGBDeviceInfo(SoIPClientDeviceDefinition deviceDefinition) + { + this.Manufacturer = deviceDefinition.Manufacturer; + this.Model = deviceDefinition.Model; + this.Hostname = deviceDefinition.Hostname; + this.Port = deviceDefinition.Port; + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/FodyWeavers.xml b/RGB.NET.Devices.SoIP/FodyWeavers.xml new file mode 100644 index 0000000..ba40f91 --- /dev/null +++ b/RGB.NET.Devices.SoIP/FodyWeavers.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/RGB.NET.Devices.SoIP/Generic/ISoIPDeviceDefinition.cs b/RGB.NET.Devices.SoIP/Generic/ISoIPDeviceDefinition.cs new file mode 100644 index 0000000..5c6dba8 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Generic/ISoIPDeviceDefinition.cs @@ -0,0 +1,8 @@ +namespace RGB.NET.Devices.SoIP.Generic +{ + /// + /// Marker interface for SoIP device definitions. + /// + public interface ISoIPDeviceDefinition + { } +} diff --git a/RGB.NET.Devices.SoIP/Generic/ISoIPRGBDevice.cs b/RGB.NET.Devices.SoIP/Generic/ISoIPRGBDevice.cs new file mode 100644 index 0000000..d7d6743 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Generic/ISoIPRGBDevice.cs @@ -0,0 +1,11 @@ +using System; +using RGB.NET.Core; + +namespace RGB.NET.Devices.SoIP.Generic +{ + // ReSharper disable once InconsistentNaming + internal interface ISoIPRGBDevice : IRGBDevice, IDisposable + { + void Initialize(IDeviceUpdateTrigger updateTrigger); + } +} diff --git a/RGB.NET.Devices.SoIP/RGB.NET.Devices.SoIP.csproj b/RGB.NET.Devices.SoIP/RGB.NET.Devices.SoIP.csproj new file mode 100644 index 0000000..16247f6 --- /dev/null +++ b/RGB.NET.Devices.SoIP/RGB.NET.Devices.SoIP.csproj @@ -0,0 +1,74 @@ + + + netstandard2.0;net45 + win7-x86;win7-x64 + + Darth Affe + Wyrez + en-US + en-US + RGB.NET.Devices.SoIP + RGB.NET.Devices.SoIP + RGB.NET.Devices.SoIP + RGB.NET.Devices.SoIP + RGB.NET.Devices.SoIP + SoIP-Device-Implementations of RGB.NET + SoIP-Device-Implementations of RGB.NET, a C# (.NET) library + Copyright © Wyrez 2017 + Copyright © Wyrez 2017 + http://lib.arge.be/icon.png + https://github.com/DarthAffe/RGB.NET + https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE + Github + https://github.com/DarthAffe/RGB.NET + True + + + + 0.0.1 + 0.0.1 + 0.0.1 + + ..\bin\ + true + True + True + latest + + + + TRACE;NETCORE;NETSTANDARD;NETSTANDARD2_0;DEBUG;NETSTANDARD2_0 + + + + NET45;NETFULL + + + + TRACE;DEBUG + true + full + false + + + + pdbonly + true + $(NoWarn);CS1591;CS1572;CS1573 + RELEASE + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RGB.NET.Devices.SoIP/Server/SoIPServerDeviceDefinition.cs b/RGB.NET.Devices.SoIP/Server/SoIPServerDeviceDefinition.cs new file mode 100644 index 0000000..2eff475 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Server/SoIPServerDeviceDefinition.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using RGB.NET.Core; +using RGB.NET.Devices.SoIP.Generic; + +namespace RGB.NET.Devices.SoIP.Server +{ + public class SoIPServerDeviceDefinition : ISoIPDeviceDefinition + { + #region Properties & Fields + + /// + /// Gets or sets the port to device is listening to. + /// + public int Port { get; set; } + + /// + /// Gets or sets the manufacturer of the device. + /// + public string Manufacturer { get; set; } = "Unknown"; + + /// + /// Gets or sets the model name of the device. + /// + public string Model { get; set; } = "Generic SoIP-Device"; + + /// + /// Gets the IDs of the leds represented by this device. + /// + public List Leds { get; } + + #endregion + + #region Constructors + + public SoIPServerDeviceDefinition(int port, params LedId[] ledIds) + { + this.Port = port; + this.Leds = ledIds.ToList(); + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs b/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs new file mode 100644 index 0000000..79c20a1 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDevice.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using RGB.NET.Core; +using RGB.NET.Devices.SoIP.Generic; +using SimpleTCP; + +namespace RGB.NET.Devices.SoIP.Server +{ + public class SoIPServerRGBDevice : AbstractRGBDevice, ISoIPRGBDevice + { + #region Properties & Fields + + private readonly List _leds; + private readonly SimpleTcpServer _tcpServer; + private SoIPServerUpdateQueue _updateQueue; + + public override SoIPServerRGBDeviceInfo DeviceInfo { get; } + + #endregion + + #region Constructors + + public SoIPServerRGBDevice(SoIPServerRGBDeviceInfo deviceInfo, List leds) + { + this.DeviceInfo = deviceInfo; + this._leds = leds; + + _tcpServer = new SimpleTcpServer(); + _tcpServer.ClientConnected += TcpServerOnClientConnected; + } + + #endregion + + #region Methods + + void ISoIPRGBDevice.Initialize(IDeviceUpdateTrigger updateTrigger) + { + int count = 0; + foreach (LedId id in _leds) + InitializeLed(id, new Rectangle((count++) * 10, 0, 10, 10)); + + //TODO DarthAffe 10.06.2018: Allow to load a layout. + + if (Size == Size.Invalid) + { + Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle)); + Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y); + } + + _tcpServer.Start(DeviceInfo.Port); + _updateQueue = new SoIPServerUpdateQueue(updateTrigger, _tcpServer); + } + + protected override void UpdateLeds(IEnumerable ledsToUpdate) => _updateQueue.SetData(ledsToUpdate); + + private void TcpServerOnClientConnected(object sender, TcpClient tcpClient) + { + string message = GetLedString(LedMapping.Values); + byte[] messageData = _tcpServer.StringEncoder.GetBytes(message + _tcpServer.StringEncoder.GetString(new[] { _tcpServer.Delimiter })); + tcpClient.GetStream().WriteAsync(messageData, 0, messageData.Length); + } + + private string GetLedString(IEnumerable leds) => string.Join(";", leds.Select(x => x.Id.ToString() + "|" + x.Color.AsARGBHexString())); + + /// + public override void Dispose() + { + base.Dispose(); + + _tcpServer.Stop(); + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDeviceInfo.cs b/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDeviceInfo.cs new file mode 100644 index 0000000..25db97e --- /dev/null +++ b/RGB.NET.Devices.SoIP/Server/SoIPServerRGBDeviceInfo.cs @@ -0,0 +1,50 @@ +using System; +using RGB.NET.Core; + +namespace RGB.NET.Devices.SoIP.Server +{ + /// + /// + /// Represents device information for a />. + /// + public class SoIPServerRGBDeviceInfo : IRGBDeviceInfo + { + #region Properties & Fields + + /// + public RGBDeviceType DeviceType => RGBDeviceType.Unknown; + + /// + public string Manufacturer { get; } + + /// + public string Model { get; } + + /// + public RGBDeviceLighting Lighting => RGBDeviceLighting.Key; + + /// + public bool SupportsSyncBack => false; + + /// + public Uri Image { get; set; } + + /// + /// The port of the device. + /// + public int Port { get; } + + #endregion + + #region Constructors + + internal SoIPServerRGBDeviceInfo(SoIPServerDeviceDefinition deviceDefinition) + { + this.Manufacturer = deviceDefinition.Manufacturer; + this.Model = deviceDefinition.Model; + this.Port = deviceDefinition.Port; + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs b/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs new file mode 100644 index 0000000..5fac483 --- /dev/null +++ b/RGB.NET.Devices.SoIP/Server/SoIPServerUpdateQueue.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RGB.NET.Core; +using SimpleTCP; + +namespace RGB.NET.Devices.SoIP.Server +{ + /// + /// + /// Represents the update-queue performing updates for E131-DMX devices. + /// + public class SoIPServerUpdateQueue : UpdateQueue + { + #region Properties & Fields + + private readonly SimpleTcpServer _tcpServer; + + #endregion + + #region Constructors + + /// + /// + /// Initializes a new instance of the class. + /// + /// The update trigger used by this queue. + /// The hostname of the device this queue is performing updates for. + public SoIPServerUpdateQueue(IDeviceUpdateTrigger updateTrigger, SimpleTcpServer tcpServer) + : base(updateTrigger) + { + this._tcpServer = tcpServer; + } + + #endregion + + #region Methods + + /// + protected override void Update(Dictionary dataSet) + { + if ((dataSet != null) && (dataSet.Count > 0)) + { + string m = GetLedString(dataSet); + _tcpServer.BroadcastLine(m); + Console.WriteLine("send " + m); + } + } + + private string GetLedString(Dictionary dataSet) => string.Join(";", dataSet.Select(x => x.Key.ToString() + "|" + x.Value.AsARGBHexString())); + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/SoIPDeviceProvider.cs b/RGB.NET.Devices.SoIP/SoIPDeviceProvider.cs new file mode 100644 index 0000000..9152b9a --- /dev/null +++ b/RGB.NET.Devices.SoIP/SoIPDeviceProvider.cs @@ -0,0 +1,139 @@ +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using RGB.NET.Core; +using RGB.NET.Devices.SoIP.Client; +using RGB.NET.Devices.SoIP.Generic; +using RGB.NET.Devices.SoIP.Server; + +namespace RGB.NET.Devices.SoIP +{ + /// + /// + /// Represents a device provider responsible for debug devices. + /// + public class SoIPDeviceProvider : IRGBDeviceProvider + { + #region Properties & Fields + + private static SoIPDeviceProvider _instance; + /// + /// Gets the singleton instance. + /// + public static SoIPDeviceProvider Instance => _instance ?? new SoIPDeviceProvider(); + + /// + public bool IsInitialized { get; private set; } + + /// + public IEnumerable Devices { get; private set; } + + /// + public bool HasExclusiveAccess => false; + + /// + /// Gets a list of all defined device-definitions. + /// + public List DeviceDefinitions { get; } = new List(); + + /// + /// The used to trigger the updates for dmx devices. + /// + public DeviceUpdateTrigger UpdateTrigger { get; private set; } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// Thrown if this constructor is called even if there is already an instance of this class. + public SoIPDeviceProvider() + { + if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SoIPDeviceProvider)}"); + _instance = this; + + UpdateTrigger = new DeviceUpdateTrigger(); + } + + #endregion + + #region Methods + + /// + /// Adds the given to this device-provider. + /// + /// The to add. + public void AddDeviceDefinition(ISoIPDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition); + + /// + public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool exclusiveAccessIfPossible = false, bool throwExceptions = false) + { + + IsInitialized = false; + + try + { + UpdateTrigger.Stop(); + + IList devices = new List(); + + foreach (ISoIPDeviceDefinition deviceDefinition in DeviceDefinitions) + { + try + { + ISoIPRGBDevice device = null; + + switch (deviceDefinition) + { + case SoIPServerDeviceDefinition serverDeviceDefinition: + if (serverDeviceDefinition.Leds.Count > 0) + device = new SoIPServerRGBDevice(new SoIPServerRGBDeviceInfo(serverDeviceDefinition), serverDeviceDefinition.Leds); + break; + + case SoIPClientDeviceDefinition clientDeviceDefinition: + device = new SoIPClientRGBDevice(new SoIPClientRGBDeviceInfo(clientDeviceDefinition)); + break; + } + + if (device != null) + { + device.Initialize(UpdateTrigger); + devices.Add(device); + } + } + catch { if (throwExceptions) throw; } + } + + UpdateTrigger.Start(); + + Devices = new ReadOnlyCollection(devices); + IsInitialized = true; + } + catch + { + if (throwExceptions) throw; + return false; + } + + return true; + } + + /// + public void ResetDevices() + { } + + /// + public void Dispose() + { + foreach (IRGBDevice device in Devices) + device.Dispose(); + } + + #endregion + } +} diff --git a/RGB.NET.Devices.SoIP/SoIPDeviceProviderLoader.cs b/RGB.NET.Devices.SoIP/SoIPDeviceProviderLoader.cs new file mode 100644 index 0000000..ead1010 --- /dev/null +++ b/RGB.NET.Devices.SoIP/SoIPDeviceProviderLoader.cs @@ -0,0 +1,24 @@ +using RGB.NET.Core; + +namespace RGB.NET.Devices.SoIP +{ + /// + /// Represents a device provider loaded used to dynamically load SoIP (syncback over IP) devices into an application. + /// + public class SoIPDeviceProviderLoader : IRGBDeviceProviderLoader + { + #region Properties & Fields + + /// + public bool RequiresInitialization => true; + + #endregion + + #region Methods + + /// + public IRGBDeviceProvider GetDeviceProvider() => SoIPDeviceProvider.Instance; + + #endregion + } +} diff --git a/RGB.NET.sln b/RGB.NET.sln index 1abfe39..db25400 100644 --- a/RGB.NET.sln +++ b/RGB.NET.sln @@ -35,6 +35,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.Razer", "RG EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.Roccat", "RGB.NET.Devices.Roccat\RGB.NET.Devices.Roccat.csproj", "{DF4A0267-24FA-4D32-8841-3E91F31E51ED}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.SoIP", "RGB.NET.Devices.SoIP\RGB.NET.Devices.SoIP.csproj", "{562CE11D-4EAA-4E98-A066-309300F3A023}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -97,6 +99,14 @@ Global {DF4A0267-24FA-4D32-8841-3E91F31E51ED}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF4A0267-24FA-4D32-8841-3E91F31E51ED}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF4A0267-24FA-4D32-8841-3E91F31E51ED}.Release|Any CPU.Build.0 = Release|Any CPU + {3B677BC5-E654-496A-8132-29DFB5CFC01A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B677BC5-E654-496A-8132-29DFB5CFC01A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B677BC5-E654-496A-8132-29DFB5CFC01A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B677BC5-E654-496A-8132-29DFB5CFC01A}.Release|Any CPU.Build.0 = Release|Any CPU + {562CE11D-4EAA-4E98-A066-309300F3A023}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {562CE11D-4EAA-4E98-A066-309300F3A023}.Debug|Any CPU.Build.0 = Debug|Any CPU + {562CE11D-4EAA-4E98-A066-309300F3A023}.Release|Any CPU.ActiveCfg = Release|Any CPU + {562CE11D-4EAA-4E98-A066-309300F3A023}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -115,6 +125,8 @@ Global {6666A8B9-DC90-46DA-A689-57489B64FF98} = {59DA384B-BE24-4486-AFC5-7DC3C9B81EB4} {A9942536-A397-405F-873A-B62CEC9C1146} = {59DA384B-BE24-4486-AFC5-7DC3C9B81EB4} {DF4A0267-24FA-4D32-8841-3E91F31E51ED} = {59DA384B-BE24-4486-AFC5-7DC3C9B81EB4} + {3B677BC5-E654-496A-8132-29DFB5CFC01A} = {59DA384B-BE24-4486-AFC5-7DC3C9B81EB4} + {562CE11D-4EAA-4E98-A066-309300F3A023} = {59DA384B-BE24-4486-AFC5-7DC3C9B81EB4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {918A9698-4B2E-44E0-8CC9-E7A7F36CCB1D} diff --git a/RGB.NET.sln.DotSettings b/RGB.NET.sln.DotSettings index 7779506..ed9c9b8 100644 --- a/RGB.NET.sln.DotSettings +++ b/RGB.NET.sln.DotSettings @@ -275,6 +275,7 @@ IBAN ID IO + IP LL PDF PLZ