diff --git a/barraider-sdtools/Backend/ISDConnection.cs b/barraider-sdtools/Backend/ISDConnection.cs index 448a28e..c29f68d 100644 --- a/barraider-sdtools/Backend/ISDConnection.cs +++ b/barraider-sdtools/Backend/ISDConnection.cs @@ -49,6 +49,10 @@ public interface ISDConnection : IDisposable /// Event received when the Property Inspector for an instance is removed from the Stream Deck software user interface, for example when selecting a different instance. /// event EventHandler> OnPropertyInspectorDidDisappear; + /// + /// Event received when the computer wakes up + /// + event EventHandler> OnSystemDidWakeUp; #endregion @@ -199,6 +203,6 @@ public interface ISDConnection : IDisposable /// StreamDeckConnection object, initialized based on the args received when launching the program /// [JsonIgnore] - streamdeck_client_csharp.StreamDeckConnection StreamDeckConnection { get; } + Communication.StreamDeckConnection StreamDeckConnection { get; } } } diff --git a/barraider-sdtools/Backend/PluginContainer.cs b/barraider-sdtools/Backend/PluginContainer.cs index 25c3f19..104eb29 100644 --- a/barraider-sdtools/Backend/PluginContainer.cs +++ b/barraider-sdtools/Backend/PluginContainer.cs @@ -1,6 +1,8 @@ -using Newtonsoft.Json.Linq; -using streamdeck_client_csharp; -using streamdeck_client_csharp.Events; +using BarRaider.SdTools.Communication; +using BarRaider.SdTools.Communication.SDEvents; +using BarRaider.SdTools.Payloads; +using BarRaider.SdTools.Wrappers; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; @@ -10,6 +12,7 @@ namespace BarRaider.SdTools { class PluginContainer { + private const int STREAMDECK_INITIAL_CONNECTION_TIMEOUT_SECONDS = 60; private StreamDeckConnection connection; private readonly ManualResetEvent connectEvent = new ManualResetEvent(false); private readonly ManualResetEvent disconnectEvent = new ManualResetEvent(false); @@ -50,14 +53,12 @@ public void Run(StreamDeckOptions options) // Start the connection connection.Run(); -#if DEBUG Logger.Instance.LogMessage(TracingLevel.DEBUG, $"Plugin Loaded: UUID: {pluginUUID} Device Info: {deviceInfo}"); -#endif Logger.Instance.LogMessage(TracingLevel.INFO, $"Plugin version: {deviceInfo.Plugin.Version}"); - Logger.Instance.LogMessage(TracingLevel.INFO, "Connecting to Stream Deck"); + Logger.Instance.LogMessage(TracingLevel.INFO, "Connecting to Stream Deck..."); - // Wait for up to 10 seconds to connect - if (connectEvent.WaitOne(TimeSpan.FromSeconds(10))) + // Time to wait for initial connection + if (connectEvent.WaitOne(TimeSpan.FromSeconds(STREAMDECK_INITIAL_CONNECTION_TIMEOUT_SECONDS))) { Logger.Instance.LogMessage(TracingLevel.INFO, "Connected to Stream Deck"); @@ -74,7 +75,7 @@ public void Run(StreamDeckOptions options) } // Button pressed - private async void Connection_OnKeyDown(object sender, StreamDeckEventReceivedEventArgs e) + private async void Connection_OnKeyDown(object sender, SDEventReceivedEventArgs e) { await instancesLock.WaitAsync(); try @@ -85,7 +86,7 @@ private async void Connection_OnKeyDown(object sender, StreamDeckEventReceivedEv if (instances.ContainsKey(e.Event.Context)) { - KeyPayload payload = new KeyPayload(GenerateKeyCoordinates(e.Event.Payload.Coordinates), + KeyPayload payload = new KeyPayload(e.Event.Payload.Coordinates, e.Event.Payload.Settings, e.Event.Payload.State, e.Event.Payload.UserDesiredState, e.Event.Payload.IsInMultiAction); instances[e.Event.Context].KeyPressed(payload); } @@ -97,7 +98,7 @@ private async void Connection_OnKeyDown(object sender, StreamDeckEventReceivedEv } // Button released - private async void Connection_OnKeyUp(object sender, StreamDeckEventReceivedEventArgs e) + private async void Connection_OnKeyUp(object sender, SDEventReceivedEventArgs e) { await instancesLock.WaitAsync(); try @@ -108,7 +109,7 @@ private async void Connection_OnKeyUp(object sender, StreamDeckEventReceivedEven if (instances.ContainsKey(e.Event.Context)) { - KeyPayload payload = new KeyPayload(GenerateKeyCoordinates(e.Event.Payload.Coordinates), + KeyPayload payload = new KeyPayload(e.Event.Payload.Coordinates, e.Event.Payload.Settings, e.Event.Payload.State, e.Event.Payload.UserDesiredState, e.Event.Payload.IsInMultiAction); instances[e.Event.Context].KeyReleased(payload); } @@ -138,7 +139,7 @@ private async void RunTick() } // Action is loaded in the Stream Deck - private async void Connection_OnWillAppear(object sender, StreamDeckEventReceivedEventArgs e) + private async void Connection_OnWillAppear(object sender, SDEventReceivedEventArgs e) { SDConnection conn = new SDConnection(connection, pluginUUID, deviceInfo, e.Event.Action, e.Event.Context, e.Event.Device); await instancesLock.WaitAsync(); @@ -157,7 +158,7 @@ private async void Connection_OnWillAppear(object sender, StreamDeckEventReceive Logger.Instance.LogMessage(TracingLevel.INFO, $"WillAppear called for already existing context {e.Event.Context} (might be inside a multi-action)"); return; } - InitialPayload payload = new InitialPayload(GenerateKeyCoordinates(e.Event.Payload.Coordinates), + InitialPayload payload = new InitialPayload(e.Event.Payload.Coordinates, e.Event.Payload.Settings, e.Event.Payload.State, e.Event.Payload.IsInMultiAction, deviceInfo); instances[e.Event.Context] = (PluginBase)Activator.CreateInstance(supportedActions[e.Event.Action], conn, payload); } @@ -177,7 +178,7 @@ private async void Connection_OnWillAppear(object sender, StreamDeckEventReceive } } - private async void Connection_OnWillDisappear(object sender, StreamDeckEventReceivedEventArgs e) + private async void Connection_OnWillDisappear(object sender, SDEventReceivedEventArgs e) { await instancesLock.WaitAsync(); try @@ -199,7 +200,7 @@ private async void Connection_OnWillDisappear(object sender, StreamDeckEventRece } // Settings updated - private async void Connection_OnDidReceiveSettings(object sender, StreamDeckEventReceivedEventArgs e) + private async void Connection_OnDidReceiveSettings(object sender, SDEventReceivedEventArgs e) { await instancesLock.WaitAsync(); try @@ -220,7 +221,7 @@ private async void Connection_OnDidReceiveSettings(object sender, StreamDeckEven } // Global settings updated - private async void Connection_OnDidReceiveGlobalSettings(object sender, StreamDeckEventReceivedEventArgs e) + private async void Connection_OnDidReceiveGlobalSettings(object sender, SDEventReceivedEventArgs e) { await instancesLock.WaitAsync(); try @@ -252,16 +253,5 @@ private void Connection_OnDisconnected(object sender, EventArgs e) Logger.Instance.LogMessage(TracingLevel.INFO, "Disconnect event received"); disconnectEvent.Set(); } - - private KeyCoordinates GenerateKeyCoordinates(Coordinates coordinates) - { - if (coordinates == null) - { - return null; - } - - return new KeyCoordinates() { Column = coordinates.Columns, Row = coordinates.Rows }; - } - } } diff --git a/barraider-sdtools/Backend/SDConnection.cs b/barraider-sdtools/Backend/SDConnection.cs index fb55a79..5357145 100644 --- a/barraider-sdtools/Backend/SDConnection.cs +++ b/barraider-sdtools/Backend/SDConnection.cs @@ -7,6 +7,8 @@ using BarRaider.SdTools.Wrappers; using BarRaider.SdTools.Events; using BarRaider.SdTools.Payloads; +using BarRaider.SdTools.Communication; +using BarRaider.SdTools.Communication.SDEvents; namespace BarRaider.SdTools { @@ -70,6 +72,10 @@ public class SDConnection : ISDConnection /// Event received when the Property Inspector for an instance is removed from the Stream Deck software user interface, for example when selecting a different instance. /// public event EventHandler> OnPropertyInspectorDidDisappear; + /// + /// Event received when the computer wakes up + /// + public event EventHandler> OnSystemDidWakeUp; #endregion @@ -145,7 +151,7 @@ public async Task SetImageAsync(string base64Image, int? state = null, bool forc if (forceSendToStreamdeck || hash != previousImageHash) { previousImageHash = hash; - await StreamDeckConnection.SetImageAsync(base64Image, ContextId, streamdeck_client_csharp.SDKTarget.HardwareAndSoftware, state); + await StreamDeckConnection.SetImageAsync(base64Image, ContextId, SDKTarget.HardwareAndSoftware, state); } } @@ -162,7 +168,7 @@ public async Task SetImageAsync(Image image, int? state = null, bool forceSendTo if (forceSendToStreamdeck || hash != previousImageHash) { previousImageHash = hash; - await StreamDeckConnection.SetImageAsync(image, ContextId, streamdeck_client_csharp.SDKTarget.HardwareAndSoftware, state); + await StreamDeckConnection.SetImageAsync(image, ContextId, SDKTarget.HardwareAndSoftware, state); } } @@ -183,7 +189,7 @@ public async Task SetDefaultImageAsync() /// public async Task SetTitleAsync(string title, int? state = null) { - await StreamDeckConnection.SetTitleAsync(title, ContextId, streamdeck_client_csharp.SDKTarget.HardwareAndSoftware, state); + await StreamDeckConnection.SetTitleAsync(title, ContextId, SDKTarget.HardwareAndSoftware, state); } /// @@ -307,7 +313,7 @@ public async Task SetStateAsync(uint state) /// StreamDeckConnection object, initialized based on the args received when launching the program /// [JsonIgnore] - public streamdeck_client_csharp.StreamDeckConnection StreamDeckConnection { get; private set; } + public StreamDeckConnection StreamDeckConnection { get; private set; } /// /// Public constructor, a StreamDeckConnection object is required along with the current action and context IDs @@ -319,7 +325,7 @@ public async Task SetStateAsync(uint state) /// /// /// /// - public SDConnection(streamdeck_client_csharp.StreamDeckConnection connection, string pluginUUID, StreamDeckInfo deviceInfo, string actionId, string contextId, string deviceId) + public SDConnection(StreamDeckConnection connection, string pluginUUID, StreamDeckInfo deviceInfo, string actionId, string contextId, string deviceId) { StreamDeckConnection = connection; this.pluginUUID = pluginUUID; @@ -336,6 +342,7 @@ public SDConnection(streamdeck_client_csharp.StreamDeckConnection connection, st StreamDeckConnection.OnDeviceDidConnect += Connection_OnDeviceDidConnect; StreamDeckConnection.OnPropertyInspectorDidAppear += Connection_OnPropertyInspectorDidAppear; StreamDeckConnection.OnPropertyInspectorDidDisappear += Connection_OnPropertyInspectorDidDisappear; + StreamDeckConnection.OnSystemDidWakeUp += StreamDeckConnection_OnSystemDidWakeUp; } /// @@ -351,12 +358,13 @@ public void Dispose() StreamDeckConnection.OnDeviceDidConnect -= Connection_OnDeviceDidConnect; StreamDeckConnection.OnPropertyInspectorDidAppear -= Connection_OnPropertyInspectorDidAppear; StreamDeckConnection.OnPropertyInspectorDidDisappear -= Connection_OnPropertyInspectorDidDisappear; + StreamDeckConnection.OnSystemDidWakeUp -= StreamDeckConnection_OnSystemDidWakeUp; } #region Event Wrappers - private void Connection_OnPropertyInspectorDidDisappear(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnPropertyInspectorDidDisappear(object sender, SDEventReceivedEventArgs e) { if (e.Event.Context == ContextId) { @@ -364,7 +372,7 @@ private void Connection_OnPropertyInspectorDidDisappear(object sender, streamdec } } - private void Connection_OnPropertyInspectorDidAppear(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnPropertyInspectorDidAppear(object sender, SDEventReceivedEventArgs e) { if (e.Event.Context == ContextId) { @@ -372,37 +380,37 @@ private void Connection_OnPropertyInspectorDidAppear(object sender, streamdeck_c } } - private void Connection_OnDeviceDidConnect(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnDeviceDidConnect(object sender, SDEventReceivedEventArgs e) { - OnDeviceDidConnect?.Invoke(this, new SDEventReceivedEventArgs(new DeviceDidConnect(e.Event.DeviceInfo.ToStreamDeckDeviceInfo(e.Event.Device)))); + OnDeviceDidConnect?.Invoke(this, new SDEventReceivedEventArgs(new DeviceDidConnect(e.Event.DeviceInfo))); } - private void Connection_OnDeviceDidDisconnect(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnDeviceDidDisconnect(object sender, SDEventReceivedEventArgs e) { OnDeviceDidDisconnect?.Invoke(this, new SDEventReceivedEventArgs(new DeviceDidDisconnect(e.Event.Device))); } - private void Connection_OnApplicationDidTerminate(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnApplicationDidTerminate(object sender, SDEventReceivedEventArgs e) { OnApplicationDidTerminate?.Invoke(this, new SDEventReceivedEventArgs(new ApplicationDidTerminate(new Payloads.ApplicationPayload(e.Event.Payload.Application)))); } - private void Connection_OnApplicationDidLaunch(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnApplicationDidLaunch(object sender, SDEventReceivedEventArgs e) { OnApplicationDidLaunch?.Invoke(this, new SDEventReceivedEventArgs(new ApplicationDidLaunch(new Payloads.ApplicationPayload(e.Event.Payload.Application)))); } - private void Connection_OnTitleParametersDidChange(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs e) { if (e.Event.Context == ContextId) { var payload = e.Event.Payload; - var newPayload = new TitleParametersPayload(payload.Settings, payload.Coordinates.ToKeyCoordinates(), payload.State, payload.Title, payload.TitleParameters.ToSDTitleParameters()); + var newPayload = new TitleParametersPayload(payload.Settings, payload.Coordinates, payload.State, payload.Title, payload.TitleParameters); OnTitleParametersDidChange?.Invoke(this, new SDEventReceivedEventArgs(new TitleParametersDidChange(e.Event.Action, e.Event.Context, e.Event.Device, newPayload))); } } - private void Connection_OnSendToPlugin(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs e) + private void Connection_OnSendToPlugin(object sender, SDEventReceivedEventArgs e) { if (e.Event.Context == ContextId) { @@ -410,6 +418,11 @@ private void Connection_OnSendToPlugin(object sender, streamdeck_client_csharp.S } } + private void StreamDeckConnection_OnSystemDidWakeUp(object sender, SDEventReceivedEventArgs e) + { + OnSystemDidWakeUp?.Invoke(this, new SDEventReceivedEventArgs(new SystemDidWakeUp())); + } + #endregion } } diff --git a/barraider-sdtools/Backend/SDWrapper.cs b/barraider-sdtools/Backend/SDWrapper.cs index 3168eee..61f86de 100644 --- a/barraider-sdtools/Backend/SDWrapper.cs +++ b/barraider-sdtools/Backend/SDWrapper.cs @@ -1,4 +1,5 @@ using BarRaider.SdTools; +using BarRaider.SdTools.Payloads; using CommandLine; using System; @@ -25,14 +26,24 @@ public static class SDWrapper /// * https://github.com/SaviorXTanren/mixer-mixitup/ /// *************************************************************************/ + + /// + /// Library's main initialization point. + /// Pass the args from your Main function. We'll handle the rest + /// + /// + public static void Run(string[] args) + { + Run(args, Tools.AutoLoadPluginActions()); + } + /// - /// Obsolete! Use the new Run(string[]) overload /// Library's main initialization point. /// Pass the args from your Main function and a list of supported PluginActionIds, the framework will handle the rest. /// /// /// - public static void Run(string[] args, PluginActionId[] supportedActionIds) + private static void Run(string[] args, PluginActionId[] supportedActionIds) { Logger.Instance.LogMessage(TracingLevel.INFO, $"Plugin [{GetExeName()}] Loading - {supportedActionIds.Length} Actions Found"); System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; @@ -41,8 +52,8 @@ public static void Run(string[] args, PluginActionId[] supportedActionIds) Logger.Instance.LogMessage(TracingLevel.DEBUG, $"Plugin Loading - Args: {String.Join(" ", args)}"); #endif - // The command line args parser expects all args to use `--`, so, let's append - for (int count = 0; count < args.Length; count++) + // The command line args parser expects all args to use `--`, so, let's append + for (int count = 0; count < args.Length; count++) { if (args[count].StartsWith("-") && !args[count].StartsWith("--")) { @@ -63,15 +74,6 @@ public static void Run(string[] args, PluginActionId[] supportedActionIds) options.WithParsed(o => RunPlugin(o, supportedActionIds)); } - /// - /// Library's main initialization point. - /// Pass the args from your Main function. We'll handle the rest - /// - /// - public static void Run(string[] args) - { - Run(args, Tools.AutoLoadPluginActions()); - } private static void RunPlugin(StreamDeckOptions options, PluginActionId[] supportedActionIds) { diff --git a/barraider-sdtools/Communication/IPayload.cs b/barraider-sdtools/Communication/IPayload.cs new file mode 100644 index 0000000..385d098 --- /dev/null +++ b/barraider-sdtools/Communication/IPayload.cs @@ -0,0 +1,6 @@ +namespace BarRaider.SdTools.Communication +{ + internal interface IPayload + { + } +} diff --git a/barraider-sdtools/Communication/Messages/EmptyPayload.cs b/barraider-sdtools/Communication/Messages/EmptyPayload.cs new file mode 100644 index 0000000..4898204 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/EmptyPayload.cs @@ -0,0 +1,9 @@ +namespace BarRaider.SdTools.Communication.Messages +{ + /// + /// Empty payload in event + /// + public class EmptyPayload : IPayload + { + } +} diff --git a/barraider-sdtools/Communication/Messages/GetGlobalSettingsMessage.cs b/barraider-sdtools/Communication/Messages/GetGlobalSettingsMessage.cs new file mode 100644 index 0000000..c194016 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/GetGlobalSettingsMessage.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class GetGlobalSettingsMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "getGlobalSettings"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + public GetGlobalSettingsMessage(string pluginUUID) + { + this.Context = pluginUUID; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/GetSettingsMessage.cs b/barraider-sdtools/Communication/Messages/GetSettingsMessage.cs new file mode 100644 index 0000000..ff76273 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/GetSettingsMessage.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class GetSettingsMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "getSettings"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + public GetSettingsMessage(string context) + { + this.Context = context; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/IMessage.cs b/barraider-sdtools/Communication/Messages/IMessage.cs new file mode 100644 index 0000000..cb1b304 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/IMessage.cs @@ -0,0 +1,7 @@ +namespace BarRaider.SdTools.Communication.Messages +{ + internal interface IMessage + { + string Event { get; } + } +} diff --git a/barraider-sdtools/Communication/Messages/LogMessage.cs b/barraider-sdtools/Communication/Messages/LogMessage.cs new file mode 100644 index 0000000..6826708 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/LogMessage.cs @@ -0,0 +1,29 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class LogMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "logMessage"; } } + + [JsonProperty("payload")] + public IPayload Payload { get; private set; } + + public LogMessage(string message) + { + this.Payload = new PayloadClass(message); + } + + private class PayloadClass : IPayload + { + [JsonProperty("message")] + public string Message { get; private set; } + + public PayloadClass(string message) + { + this.Message = message; + } + } + } +} diff --git a/barraider-sdtools/Communication/Messages/OpenUrlMessage.cs b/barraider-sdtools/Communication/Messages/OpenUrlMessage.cs new file mode 100644 index 0000000..6ab6a8e --- /dev/null +++ b/barraider-sdtools/Communication/Messages/OpenUrlMessage.cs @@ -0,0 +1,30 @@ +using Newtonsoft.Json; +using System; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class OpenUrlMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "openUrl"; } } + + [JsonProperty("payload")] + public IPayload Payload { get; private set; } + + public OpenUrlMessage(Uri uri) + { + this.Payload = new PayloadClass(uri); + } + + private class PayloadClass : IPayload + { + [JsonProperty("url")] + public string Url { get; private set; } + + public PayloadClass(Uri uri) + { + this.Url = uri.ToString(); + } + } + } +} diff --git a/barraider-sdtools/Communication/Messages/RegisterEventMessage.cs b/barraider-sdtools/Communication/Messages/RegisterEventMessage.cs new file mode 100644 index 0000000..c4ea9d8 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/RegisterEventMessage.cs @@ -0,0 +1,20 @@ +using Newtonsoft.Json; +using System; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class RegisterEventMessage : IMessage + { + [JsonProperty("event")] + public string Event { get; private set; } + + [JsonProperty("uuid")] + public string UUID { get; private set; } + + public RegisterEventMessage(string eventName, string uuid) + { + this.Event = eventName; + this.UUID = uuid; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SendToPropertyInspectorMessage.cs b/barraider-sdtools/Communication/Messages/SendToPropertyInspectorMessage.cs new file mode 100644 index 0000000..712c78b --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SendToPropertyInspectorMessage.cs @@ -0,0 +1,27 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SendToPropertyInspectorMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "sendToPropertyInspector"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("payload")] + public JObject Payload { get; private set; } + + [JsonProperty("action")] + public string Action { get; private set; } + + public SendToPropertyInspectorMessage(string action, JObject data, string context) + { + this.Context = context; + this.Payload = data; + this.Action = action; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SetGlobalSettingsMessage.cs b/barraider-sdtools/Communication/Messages/SetGlobalSettingsMessage.cs new file mode 100644 index 0000000..a9f90be --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SetGlobalSettingsMessage.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SetGlobalSettingsMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "setGlobalSettings"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("payload")] + public JObject Payload { get; private set; } + + public SetGlobalSettingsMessage(JObject settings, string pluginUUID) + { + this.Context = pluginUUID; + this.Payload = settings; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SetImageMessage.cs b/barraider-sdtools/Communication/Messages/SetImageMessage.cs new file mode 100644 index 0000000..1a6fc88 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SetImageMessage.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SetImageMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "setImage"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("payload")] + public IPayload Payload { get; private set; } + + public SetImageMessage(string base64Image, string context, SDKTarget target, int? state) + { + this.Context = context; + this.Payload = new PayloadClass(base64Image, target, state); + } + + private class PayloadClass : IPayload + { + [JsonProperty("image")] + public string Image { get; private set; } + + [JsonProperty("target")] + public SDKTarget Target { get; private set; } + + [JsonProperty("state", NullValueHandling = NullValueHandling.Ignore)] + public int? State { get; private set; } + + public PayloadClass(string image, SDKTarget target, int? state) + { + this.Image = image; + this.Target = target; + this.State = state; + } + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SetSettingsMessage.cs b/barraider-sdtools/Communication/Messages/SetSettingsMessage.cs new file mode 100644 index 0000000..93fc5fb --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SetSettingsMessage.cs @@ -0,0 +1,23 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SetSettingsMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "setSettings"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("payload")] + public JObject Payload { get; private set; } + + public SetSettingsMessage(JObject settings, string context) + { + this.Context = context; + this.Payload = settings; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SetStateMessage.cs b/barraider-sdtools/Communication/Messages/SetStateMessage.cs new file mode 100644 index 0000000..a6c3659 --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SetStateMessage.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SetStateMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "setState"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("payload")] + public IPayload Payload { get; private set; } + + public SetStateMessage(uint state, string context) + { + this.Context = context; + this.Payload = new PayloadClass(state); + } + + private class PayloadClass : IPayload + { + [JsonProperty("state")] + public uint State { get; private set; } + + public PayloadClass(uint state) + { + this.State = state; + } + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SetTitleMessage.cs b/barraider-sdtools/Communication/Messages/SetTitleMessage.cs new file mode 100644 index 0000000..d094bda --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SetTitleMessage.cs @@ -0,0 +1,41 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SetTitleMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "setTitle"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("payload")] + public IPayload Payload { get; private set; } + + public SetTitleMessage(string title, string context, SDKTarget target, int? state) + { + this.Context = context; + this.Payload = new PayloadClass(title, target, state); + } + + private class PayloadClass : IPayload + { + [JsonProperty("title")] + public string Title { get; private set; } + + [JsonProperty("target")] + public SDKTarget Target { get; private set; } + + [JsonProperty("state", NullValueHandling = NullValueHandling.Ignore)] + public int? State { get; private set; } + + public PayloadClass(string title, SDKTarget target, int? state) + { + this.Title = title; + this.Target = target; + this.State = state; + } + } + } +} diff --git a/barraider-sdtools/Communication/Messages/ShowAlertMessage.cs b/barraider-sdtools/Communication/Messages/ShowAlertMessage.cs new file mode 100644 index 0000000..c4d1fde --- /dev/null +++ b/barraider-sdtools/Communication/Messages/ShowAlertMessage.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class ShowAlertMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "showAlert"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + public ShowAlertMessage(string context) + { + this.Context = context; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/ShowOkMessage.cs b/barraider-sdtools/Communication/Messages/ShowOkMessage.cs new file mode 100644 index 0000000..bc9477e --- /dev/null +++ b/barraider-sdtools/Communication/Messages/ShowOkMessage.cs @@ -0,0 +1,18 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class ShowOkMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "showOk"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + public ShowOkMessage(string context) + { + this.Context = context; + } + } +} diff --git a/barraider-sdtools/Communication/Messages/SwitchToProfileMessage.cs b/barraider-sdtools/Communication/Messages/SwitchToProfileMessage.cs new file mode 100644 index 0000000..464911a --- /dev/null +++ b/barraider-sdtools/Communication/Messages/SwitchToProfileMessage.cs @@ -0,0 +1,44 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.Messages +{ + internal class SwitchToProfileMessage : IMessage + { + [JsonProperty("event")] + public string Event { get { return "switchToProfile"; } } + + [JsonProperty("context")] + public string Context { get; private set; } + + [JsonProperty("device")] + public string Device { get; private set; } + + [JsonProperty("payload")] + public IPayload Payload { get; private set; } + + public SwitchToProfileMessage(string device, string profileName, string pluginUUID) + { + this.Context = pluginUUID; + this.Device = device; + if (!string.IsNullOrEmpty(profileName)) + { + this.Payload = new PayloadClass(profileName); + } + else + { + this.Payload = new EmptyPayload(); + } + } + + private class PayloadClass : IPayload + { + [JsonProperty("profile")] + public string Profile { get; private set; } + + public PayloadClass(string profile) + { + this.Profile = profile; + } + } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/AppearancePayload.cs b/barraider-sdtools/Communication/SDEvents/AppearancePayload.cs new file mode 100644 index 0000000..1ead753 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/AppearancePayload.cs @@ -0,0 +1,35 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for Apperance settings + /// + public class AppearancePayload + { + /// + /// Additional settings + /// + [JsonProperty("settings")] + public JObject Settings { get; private set; } + + /// + /// Coordinates of key pressed + /// + [JsonProperty("coordinates")] + public KeyCoordinates Coordinates { get; private set; } + + /// + /// State of key + /// + [JsonProperty("state")] + public uint State { get; private set; } + + /// + /// Is action in MultiAction + /// + [JsonProperty("isInMultiAction")] + public bool IsInMultiAction { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/ApplicationDidLaunchEvent.cs b/barraider-sdtools/Communication/SDEvents/ApplicationDidLaunchEvent.cs new file mode 100644 index 0000000..78dee6d --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/ApplicationDidLaunchEvent.cs @@ -0,0 +1,17 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for ApplicationDidLaunch event + /// + public class ApplicationDidLaunchEvent : BaseEvent + { + /// + /// Application information + /// + [JsonProperty("payload")] + public ApplicationPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/ApplicationDidTerminateEvent.cs b/barraider-sdtools/Communication/SDEvents/ApplicationDidTerminateEvent.cs new file mode 100644 index 0000000..e5e790f --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/ApplicationDidTerminateEvent.cs @@ -0,0 +1,17 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for ApplicationDidTerminate Event + /// + public class ApplicationDidTerminateEvent : BaseEvent + { + /// + /// Application payload + /// + [JsonProperty("payload")] + public ApplicationPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/BaseEvent.cs b/barraider-sdtools/Communication/SDEvents/BaseEvent.cs new file mode 100644 index 0000000..47b5195 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/BaseEvent.cs @@ -0,0 +1,86 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// List of all supported event typs + /// + internal static class EventTypes + { + public const string KeyDown = "keyDown"; + public const string KeyUp = "keyUp"; + public const string WillAppear = "willAppear"; + public const string WillDisappear = "willDisappear"; + public const string TitleParametersDidChange = "titleParametersDidChange"; + public const string DeviceDidConnect = "deviceDidConnect"; + public const string DeviceDidDisconnect = "deviceDidDisconnect"; + public const string ApplicationDidLaunch = "applicationDidLaunch"; + public const string ApplicationDidTerminate = "applicationDidTerminate"; + public const string SystemDidWakeUp = "systemDidWakeUp"; + public const string DidReceiveSettings = "didReceiveSettings"; + public const string DidReceiveGlobalSettings = "didReceiveGlobalSettings"; + public const string PropertyInspectorDidAppear = "propertyInspectorDidAppear"; + public const string PropertyInspectorDidDisappear = "propertyInspectorDidDisappear"; + public const string SendToPlugin = "sendToPlugin"; + } + + /// + /// Base event that all the actual events derive from + /// + public abstract class BaseEvent + { + private static readonly Dictionary eventsMap = new Dictionary + { + { EventTypes.KeyDown, typeof(KeyDownEvent) }, + { EventTypes.KeyUp, typeof(KeyUpEvent) }, + + { EventTypes.WillAppear, typeof(WillAppearEvent) }, + { EventTypes.WillDisappear, typeof(WillDisappearEvent) }, + + { EventTypes.TitleParametersDidChange, typeof(TitleParametersDidChangeEvent) }, + + { EventTypes.DeviceDidConnect, typeof(DeviceDidConnectEvent) }, + { EventTypes.DeviceDidDisconnect, typeof(DeviceDidDisconnectEvent) }, + + { EventTypes.ApplicationDidLaunch, typeof(ApplicationDidLaunchEvent) }, + { EventTypes.ApplicationDidTerminate, typeof(ApplicationDidTerminateEvent) }, + + { EventTypes.SystemDidWakeUp, typeof(SystemDidWakeUpEvent) }, + + { EventTypes.DidReceiveSettings, typeof(DidReceiveSettingsEvent) }, + { EventTypes.DidReceiveGlobalSettings, typeof(DidReceiveGlobalSettingsEvent) }, + + { EventTypes.PropertyInspectorDidAppear, typeof(PropertyInspectorDidAppearEvent) }, + { EventTypes.PropertyInspectorDidDisappear, typeof(PropertyInspectorDidDisappearEvent) }, + + { EventTypes.SendToPlugin, typeof(SendToPluginEvent) }, + }; + + /// + /// Name of the event raised + /// + [JsonProperty("event")] + public string Event { get; set; } + + internal static BaseEvent Parse(string json) + { + JObject jsonObject = JObject.Parse(json); + if (!jsonObject.ContainsKey("event")) + { + return null; + } + + string eventType = jsonObject["event"].ToString(); + if (!eventsMap.ContainsKey(eventType)) + { + return null; + } + + return JsonConvert.DeserializeObject(json, eventsMap[eventType]) as BaseEvent; + } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/DeviceDidConnectEvent.cs b/barraider-sdtools/Communication/SDEvents/DeviceDidConnectEvent.cs new file mode 100644 index 0000000..e10925d --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/DeviceDidConnectEvent.cs @@ -0,0 +1,22 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for DeviceDidConnect Event + /// + public class DeviceDidConnectEvent : BaseEvent + { + /// + /// UUID of device + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// Information on the device connected + /// + [JsonProperty("deviceInfo")] + public StreamDeckDeviceInfo DeviceInfo { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/DeviceDidDisconnectEvent.cs b/barraider-sdtools/Communication/SDEvents/DeviceDidDisconnectEvent.cs new file mode 100644 index 0000000..de1eab9 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/DeviceDidDisconnectEvent.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for DeviceDidDisconnect Event + /// + public class DeviceDidDisconnectEvent : BaseEvent + { + /// + /// UUID of device that was disconnected + /// + [JsonProperty("device")] + public string Device { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/DidReceiveGlobalSettingsEvent.cs b/barraider-sdtools/Communication/SDEvents/DidReceiveGlobalSettingsEvent.cs new file mode 100644 index 0000000..d78d993 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/DidReceiveGlobalSettingsEvent.cs @@ -0,0 +1,17 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for DidReceiveGlobalSettings Event + /// + public class DidReceiveGlobalSettingsEvent : BaseEvent + { + /// + /// Global Settings payload + /// + [JsonProperty("payload")] + public ReceivedGlobalSettingsPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/DidReceiveSettingsEvent.cs b/barraider-sdtools/Communication/SDEvents/DidReceiveSettingsEvent.cs new file mode 100644 index 0000000..8caedc6 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/DidReceiveSettingsEvent.cs @@ -0,0 +1,35 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for DidReceiveSettings Event + /// + public class DidReceiveSettingsEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Context (unique action UUID) + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Device UUID action is on + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// Settings for action + /// + [JsonProperty("payload")] + public ReceivedSettingsPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/KeyDownEvent.cs b/barraider-sdtools/Communication/SDEvents/KeyDownEvent.cs new file mode 100644 index 0000000..bec7213 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/KeyDownEvent.cs @@ -0,0 +1,38 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for KeyDown event + /// + public class KeyDownEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Device UUID key was pressed on + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// Information on key + /// + [JsonProperty("payload")] + public KeyPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/KeyUpEvent.cs b/barraider-sdtools/Communication/SDEvents/KeyUpEvent.cs new file mode 100644 index 0000000..83e7ea4 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/KeyUpEvent.cs @@ -0,0 +1,35 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for KeyUp event + /// + public class KeyUpEvent : BaseEvent + { + /// + /// Action name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Stream Deck device UUID + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// Key settings + /// + [JsonProperty("payload")] + public KeyPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/PropertyInspectorDidAppearEvent.cs b/barraider-sdtools/Communication/SDEvents/PropertyInspectorDidAppearEvent.cs new file mode 100644 index 0000000..1802f10 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/PropertyInspectorDidAppearEvent.cs @@ -0,0 +1,29 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for PropertyInspectorDidAppearEvent event + /// + public class PropertyInspectorDidAppearEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Stream Deck device UUID + /// + [JsonProperty("device")] + public string Device { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/PropertyInspectorDidDisappearEvent.cs b/barraider-sdtools/Communication/SDEvents/PropertyInspectorDidDisappearEvent.cs new file mode 100644 index 0000000..e9ff7f3 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/PropertyInspectorDidDisappearEvent.cs @@ -0,0 +1,29 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for PropertyInspectorDidDisappearEvent event + /// + public class PropertyInspectorDidDisappearEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Stream Deck device UUID + /// + [JsonProperty("device")] + public string Device { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/SendToPluginEvent.cs b/barraider-sdtools/Communication/SDEvents/SendToPluginEvent.cs new file mode 100644 index 0000000..b94208a --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/SendToPluginEvent.cs @@ -0,0 +1,29 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for SendToPluginEvent event + /// + public class SendToPluginEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Payload + /// + [JsonProperty("payload")] + public JObject Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/SystemDidWakeUpEvent.cs b/barraider-sdtools/Communication/SDEvents/SystemDidWakeUpEvent.cs new file mode 100644 index 0000000..269128e --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/SystemDidWakeUpEvent.cs @@ -0,0 +1,12 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for SystemDidWakeUp event + /// + public class SystemDidWakeUpEvent : BaseEvent + { + } +} diff --git a/barraider-sdtools/Communication/SDEvents/TitleParametersDidChangeEvent.cs b/barraider-sdtools/Communication/SDEvents/TitleParametersDidChangeEvent.cs new file mode 100644 index 0000000..2681f6c --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/TitleParametersDidChangeEvent.cs @@ -0,0 +1,35 @@ +using BarRaider.SdTools.Payloads; +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for TitleParametersDidChangeEvent event + /// + public class TitleParametersDidChangeEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Stream Deck device UUID + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// Title settings + /// + [JsonProperty("payload")] + public TitleParametersPayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/WillAppearEvent.cs b/barraider-sdtools/Communication/SDEvents/WillAppearEvent.cs new file mode 100644 index 0000000..1409462 --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/WillAppearEvent.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for WillAppearEvent event + /// + public class WillAppearEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Stream Deck device UUID + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// Appearance settings + /// + [JsonProperty("payload")] + public AppearancePayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDEvents/WillDisappearEvent.cs b/barraider-sdtools/Communication/SDEvents/WillDisappearEvent.cs new file mode 100644 index 0000000..c80c7bd --- /dev/null +++ b/barraider-sdtools/Communication/SDEvents/WillDisappearEvent.cs @@ -0,0 +1,34 @@ +using Newtonsoft.Json; + +namespace BarRaider.SdTools.Communication.SDEvents +{ + /// + /// Payload for WillDisappearEvent event + /// + public class WillDisappearEvent : BaseEvent + { + /// + /// Action Name + /// + [JsonProperty("action")] + public string Action { get; private set; } + + /// + /// Unique Action UUID + /// + [JsonProperty("context")] + public string Context { get; private set; } + + /// + /// Stream Deck device UUID + /// + [JsonProperty("device")] + public string Device { get; private set; } + + /// + /// settings + /// + [JsonProperty("payload")] + public AppearancePayload Payload { get; private set; } + } +} diff --git a/barraider-sdtools/Communication/SDKTarget.cs b/barraider-sdtools/Communication/SDKTarget.cs new file mode 100644 index 0000000..8d9e9d2 --- /dev/null +++ b/barraider-sdtools/Communication/SDKTarget.cs @@ -0,0 +1,23 @@ +namespace BarRaider.SdTools.Communication +{ + /// + /// Target to send Title/Image to + /// + public enum SDKTarget : int + { + /// + /// Send to both App and Device + /// + HardwareAndSoftware = 0, + + /// + /// Send only to device + /// + HardwareOnly = 1, + + /// + /// Send only to app + /// + SoftwareOnly = 2, + } +} diff --git a/barraider-sdtools/Communication/StreamDeckConnection.cs b/barraider-sdtools/Communication/StreamDeckConnection.cs new file mode 100644 index 0000000..15c179c --- /dev/null +++ b/barraider-sdtools/Communication/StreamDeckConnection.cs @@ -0,0 +1,398 @@ +using BarRaider.SdTools.Communication.Messages; +using BarRaider.SdTools.Communication.SDEvents; +using BarRaider.SdTools.Wrappers; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace BarRaider.SdTools.Communication +{ + /// + /// Underlying object that communicates with the stream deck app + /// + public class StreamDeckConnection + { + private const int BufferSize = 1024 * 1024; + + private ClientWebSocket webSocket; + private readonly SemaphoreSlim sendSocketSemaphore = new SemaphoreSlim(1); + private readonly CancellationTokenSource cancelTokenSource = new CancellationTokenSource(); + private readonly string registerEvent; + + /// + /// The port used to connect to the StreamDeck websocket + /// + public int Port { get; private set; } + + /// + /// This is the unique identifier used to communicate with the register StreamDeck plugin. + /// + public string UUID { get; private set; } + + /// + /// Raised when plugin is connected to stream deck app + /// + public event EventHandler OnConnected; + + /// + /// /// Raised when plugin is disconnected from stream deck app + /// + public event EventHandler OnDisconnected; + + /// + /// Raised when key is pushed down + /// + public event EventHandler> OnKeyDown; + + /// + /// Raised when key is released + /// + public event EventHandler> OnKeyUp; + + /// + /// Raised when the action is shown, main trigger for a PluginAction + /// + public event EventHandler> OnWillAppear; + + /// + /// Raised when the action is no longer shown, main trigger for Dispose of PluginAction + /// + public event EventHandler> OnWillDisappear; + + /// + /// Contains information on the Title and its style + /// + public event EventHandler> OnTitleParametersDidChange; + + /// + /// Raised when a Stream Deck device is connected to the PC + /// + public event EventHandler> OnDeviceDidConnect; + + /// + /// Raised when a Stream Deck device has disconnected from the PC + /// + public event EventHandler> OnDeviceDidDisconnect; + + /// + /// Raised when a monitored app is launched/active + /// + public event EventHandler> OnApplicationDidLaunch; + + /// + /// Raised when a monitored app is terminated + /// + public event EventHandler> OnApplicationDidTerminate; + + /// + /// Raised after the PC wakes up from sleep + /// + public event EventHandler> OnSystemDidWakeUp; + + /// + /// Raised when settings for the action are received + /// + public event EventHandler> OnDidReceiveSettings; + + /// + /// Raised when global settings for the entire plugin are received + /// + public event EventHandler> OnDidReceiveGlobalSettings; + + /// + /// Raised when the user is viewing the settings in the Stream Deck app + /// + public event EventHandler> OnPropertyInspectorDidAppear; + + /// + /// Raised when the user stops viewing the settings in the Stream Deck app + /// + public event EventHandler> OnPropertyInspectorDidDisappear; + + /// + /// Raised when a payload is sent to the plugin from the PI + /// + public event EventHandler> OnSendToPlugin; + + internal StreamDeckConnection(int port, string uuid, string registerEvent) + { + this.Port = port; + this.UUID = uuid; + this.registerEvent = registerEvent; + } + + internal void Run() + { + if (webSocket == null) + { + webSocket = new ClientWebSocket(); + _ = this.RunAsync(); + } + } + + internal void Stop() + { + cancelTokenSource.Cancel(); + } + + internal Task SetTitleAsync(string title, string context, SDKTarget target, int? state) + { + return SendAsync(new SetTitleMessage(title, context, target, state)); + } + + internal Task LogMessageAsync(string message) + { + return SendAsync(new LogMessage(message)); + } + + internal Task SetImageAsync(Image image, string context, SDKTarget target, int? state) + { + using (MemoryStream memoryStream = new MemoryStream()) + { + image.Save(memoryStream, ImageFormat.Png); + byte[] imageBytes = memoryStream.ToArray(); + + // Convert byte[] to Base64 String + string base64String = $"data:image/png;base64,{Convert.ToBase64String(imageBytes)}"; + return SetImageAsync(base64String, context, target, state); + } + } + + internal Task SetImageAsync(string base64Image, string context, SDKTarget target, int? state) + { + return SendAsync(new SetImageMessage(base64Image, context, target, state)); + } + + internal Task ShowAlertAsync(string context) + { + return SendAsync(new ShowAlertMessage(context)); + } + + internal Task ShowOkAsync(string context) + { + return SendAsync(new ShowOkMessage(context)); + } + + internal Task SetGlobalSettingsAsync(JObject settings) + { + return SendAsync(new SetGlobalSettingsMessage(settings, this.UUID)); + } + + internal Task GetGlobalSettingsAsync() + { + return SendAsync(new GetGlobalSettingsMessage(this.UUID)); + } + + internal Task SetSettingsAsync(JObject settings, string context) + { + return SendAsync(new SetSettingsMessage(settings, context)); + } + + internal Task GetSettingsAsync(string context) + { + return SendAsync(new GetSettingsMessage(context)); + } + + internal Task SetStateAsync(uint state, string context) + { + return SendAsync(new SetStateMessage(state, context)); + } + + internal Task SendToPropertyInspectorAsync(string action, JObject data, string context) + { + return SendAsync(new SendToPropertyInspectorMessage(action, data, context)); + } + + internal Task SwitchToProfileAsync(string device, string profileName, string context) + { + return SendAsync(new SwitchToProfileMessage(device, profileName, context)); + } + internal Task OpenUrlAsync(string uri) + { + return OpenUrlAsync(new Uri(uri)); + } + + internal Task OpenUrlAsync(Uri uri) + { + return SendAsync(new OpenUrlMessage(uri)); + } + + internal Task SendAsync(IMessage message) + { + return SendAsync(JsonConvert.SerializeObject(message)); + } + + #region Private Methods + + private async Task SendAsync(string text) + { + try + { + if (webSocket != null) + { + try + { + await sendSocketSemaphore.WaitAsync(); + byte[] buffer = Encoding.UTF8.GetBytes(text); + await webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, cancelTokenSource.Token); + } + finally + { + sendSocketSemaphore.Release(); + } + } + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.FATAL, $"{this.GetType()} SendAsync Exception: {ex}"); + await DisconnectAsync(); + } + + } + + private async Task RunAsync() + { + try + { + await webSocket.ConnectAsync(new Uri($"ws://localhost:{this.Port}"), cancelTokenSource.Token); + if (webSocket.State != WebSocketState.Open) + { + + Logger.Instance.LogMessage(TracingLevel.FATAL, $"{this.GetType()} RunAsync failed - Websocket not open {webSocket.State}"); + await DisconnectAsync(); + return; + } + + await SendAsync(new RegisterEventMessage(registerEvent, this.UUID)); + + OnConnected?.Invoke(this, new EventArgs()); + await ReceiveAsync(); + } + finally + { + Logger.Instance.LogMessage(TracingLevel.INFO, $"{this.GetType()} RunAsync completed, shutting down"); + await DisconnectAsync(); + } + } + + private async Task ReceiveAsync() + { + byte[] buffer = new byte[BufferSize]; + ArraySegment arrayBuffer = new ArraySegment(buffer); + StringBuilder textBuffer = new StringBuilder(BufferSize); + + try + { + while (!cancelTokenSource.IsCancellationRequested && webSocket != null) + { + WebSocketReceiveResult result = await webSocket.ReceiveAsync(arrayBuffer, cancelTokenSource.Token); + + if (result != null) + { + if (result.MessageType == WebSocketMessageType.Close || + (result.CloseStatus != null && result.CloseStatus.HasValue && result.CloseStatus.Value != WebSocketCloseStatus.Empty)) + { + return result.CloseStatus.GetValueOrDefault(); + } + else if (result.MessageType == WebSocketMessageType.Text) + { + textBuffer.Append(Encoding.UTF8.GetString(buffer, 0, result.Count)); + if (result.EndOfMessage) + { +#if DEBUG + Logger.Instance.LogMessage(TracingLevel.DEBUG, $"Incoming Message: {textBuffer}"); +#endif + + string strBuffer = textBuffer.ToString(); + textBuffer.Clear(); + BaseEvent evt = BaseEvent.Parse(strBuffer); + if (evt == null) + { + Logger.Instance.LogMessage(TracingLevel.FATAL, $"{this.GetType()} Unknown event received from Stream Deck: {strBuffer}"); + continue; + } + + _ = Task.Run(() => + { + try + { + switch (evt.Event) + { + case EventTypes.KeyDown: OnKeyDown?.Invoke(this, new SDEventReceivedEventArgs(evt as KeyDownEvent)); break; + case EventTypes.KeyUp: OnKeyUp?.Invoke(this, new SDEventReceivedEventArgs(evt as KeyUpEvent)); break; + case EventTypes.WillAppear: OnWillAppear?.Invoke(this, new SDEventReceivedEventArgs(evt as WillAppearEvent)); break; + case EventTypes.WillDisappear: OnWillDisappear?.Invoke(this, new SDEventReceivedEventArgs(evt as WillDisappearEvent)); break; + case EventTypes.TitleParametersDidChange: OnTitleParametersDidChange?.Invoke(this, new SDEventReceivedEventArgs(evt as TitleParametersDidChangeEvent)); break; + case EventTypes.DeviceDidConnect: OnDeviceDidConnect?.Invoke(this, new SDEventReceivedEventArgs(evt as DeviceDidConnectEvent)); break; + case EventTypes.DeviceDidDisconnect: OnDeviceDidDisconnect?.Invoke(this, new SDEventReceivedEventArgs(evt as DeviceDidDisconnectEvent)); break; + case EventTypes.ApplicationDidLaunch: OnApplicationDidLaunch?.Invoke(this, new SDEventReceivedEventArgs(evt as ApplicationDidLaunchEvent)); break; + case EventTypes.ApplicationDidTerminate: OnApplicationDidTerminate?.Invoke(this, new SDEventReceivedEventArgs(evt as ApplicationDidTerminateEvent)); break; + case EventTypes.SystemDidWakeUp: OnSystemDidWakeUp?.Invoke(this, new SDEventReceivedEventArgs(evt as SystemDidWakeUpEvent)); break; + case EventTypes.DidReceiveSettings: OnDidReceiveSettings?.Invoke(this, new SDEventReceivedEventArgs(evt as DidReceiveSettingsEvent)); break; + case EventTypes.DidReceiveGlobalSettings: OnDidReceiveGlobalSettings?.Invoke(this, new SDEventReceivedEventArgs(evt as DidReceiveGlobalSettingsEvent)); break; + case EventTypes.PropertyInspectorDidAppear: OnPropertyInspectorDidAppear?.Invoke(this, new SDEventReceivedEventArgs(evt as PropertyInspectorDidAppearEvent)); break; + case EventTypes.PropertyInspectorDidDisappear: OnPropertyInspectorDidDisappear?.Invoke(this, new SDEventReceivedEventArgs(evt as PropertyInspectorDidDisappearEvent)); break; + case EventTypes.SendToPlugin: OnSendToPlugin?.Invoke(this, new SDEventReceivedEventArgs(evt as SendToPluginEvent)); break; + default: + Logger.Instance.LogMessage(TracingLevel.WARN, $"{this.GetType()} Unsupported Stream Deck event: {strBuffer}"); + break; + } + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"{this.GetType()} Unhandled 3rd party exception when triggering {evt.Event} event. Exception: {ex}"); + } + }); + } + } + } + } + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.FATAL, $"{this.GetType()} ReceiveAsync Exception: {ex}"); + } + + return WebSocketCloseStatus.NormalClosure; + } + + private async Task DisconnectAsync() + { + if (webSocket != null) + { + ClientWebSocket socket = webSocket; + webSocket = null; + + try + { + await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Disconnecting", cancelTokenSource.Token); + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"{this.GetType()} DisconnectAsync failed to close connection. Exception: {ex}"); + } + + + try + { + socket.Dispose(); + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"{this.GetType()} DisconnectAsync failed to dispose websocket. Exception: {ex}"); + } + + OnDisconnected?.Invoke(this, EventArgs.Empty); + } + } + + #endregion + } +} diff --git a/barraider-sdtools/Events/ApplicationDidLaunch.cs b/barraider-sdtools/Events/ApplicationDidLaunch.cs index 6ccde14..ad79ad8 100644 --- a/barraider-sdtools/Events/ApplicationDidLaunch.cs +++ b/barraider-sdtools/Events/ApplicationDidLaunch.cs @@ -1,9 +1,5 @@ using BarRaider.SdTools.Payloads; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/ApplicationDidTerminate.cs b/barraider-sdtools/Events/ApplicationDidTerminate.cs index 753ced3..d869cf7 100644 --- a/barraider-sdtools/Events/ApplicationDidTerminate.cs +++ b/barraider-sdtools/Events/ApplicationDidTerminate.cs @@ -1,9 +1,5 @@ using BarRaider.SdTools.Payloads; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/DeviceDidConnect.cs b/barraider-sdtools/Events/DeviceDidConnect.cs index 42b67de..4fe2eed 100644 --- a/barraider-sdtools/Events/DeviceDidConnect.cs +++ b/barraider-sdtools/Events/DeviceDidConnect.cs @@ -1,8 +1,4 @@ using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/DeviceDidDisconnect.cs b/barraider-sdtools/Events/DeviceDidDisconnect.cs index 158c89e..b5d2af8 100644 --- a/barraider-sdtools/Events/DeviceDidDisconnect.cs +++ b/barraider-sdtools/Events/DeviceDidDisconnect.cs @@ -1,8 +1,5 @@ using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/PropertyInspectorDidAppear.cs b/barraider-sdtools/Events/PropertyInspectorDidAppear.cs index de92c1a..d593329 100644 --- a/barraider-sdtools/Events/PropertyInspectorDidAppear.cs +++ b/barraider-sdtools/Events/PropertyInspectorDidAppear.cs @@ -1,8 +1,4 @@ using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/PropertyInspectorDidDisappear.cs b/barraider-sdtools/Events/PropertyInspectorDidDisappear.cs index 48c8e6c..4496c5c 100644 --- a/barraider-sdtools/Events/PropertyInspectorDidDisappear.cs +++ b/barraider-sdtools/Events/PropertyInspectorDidDisappear.cs @@ -1,8 +1,4 @@ using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/SendToPlugin.cs b/barraider-sdtools/Events/SendToPlugin.cs index 72429b2..fdcaae1 100644 --- a/barraider-sdtools/Events/SendToPlugin.cs +++ b/barraider-sdtools/Events/SendToPlugin.cs @@ -1,8 +1,5 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Events/SystemDidWakeUp.cs b/barraider-sdtools/Events/SystemDidWakeUp.cs new file mode 100644 index 0000000..bf8665f --- /dev/null +++ b/barraider-sdtools/Events/SystemDidWakeUp.cs @@ -0,0 +1,15 @@ +namespace BarRaider.SdTools.Events +{ + /// + /// Payload for SystemDidWakeUp event + /// + public class SystemDidWakeUp + { + /// + /// Constructor + /// + public SystemDidWakeUp() + { + } + } +} diff --git a/barraider-sdtools/Events/TitleParametersDidChange.cs b/barraider-sdtools/Events/TitleParametersDidChange.cs index 50aa9a5..ead6beb 100644 --- a/barraider-sdtools/Events/TitleParametersDidChange.cs +++ b/barraider-sdtools/Events/TitleParametersDidChange.cs @@ -1,9 +1,5 @@ using BarRaider.SdTools.Payloads; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Text; namespace BarRaider.SdTools.Events { diff --git a/barraider-sdtools/Payloads/KeyPayload.cs b/barraider-sdtools/Payloads/KeyPayload.cs index 95a50e5..e9259f4 100644 --- a/barraider-sdtools/Payloads/KeyPayload.cs +++ b/barraider-sdtools/Payloads/KeyPayload.cs @@ -54,5 +54,10 @@ public KeyPayload(KeyCoordinates coordinates, JObject settings, uint state, uint UserDesiredState = userDesiredState; IsInMultiAction = isInMultiAction; } + + /// + /// For Seralization + /// + public KeyPayload() { } } } diff --git a/barraider-sdtools/Payloads/StreamDeckOptions.cs b/barraider-sdtools/Payloads/StreamDeckOptions.cs index 72a5029..815cf85 100644 --- a/barraider-sdtools/Payloads/StreamDeckOptions.cs +++ b/barraider-sdtools/Payloads/StreamDeckOptions.cs @@ -1,7 +1,7 @@ using CommandLine; using Newtonsoft.Json.Linq; -namespace BarRaider.SdTools +namespace BarRaider.SdTools.Payloads { /// /// Class holding all the information passed to the plugin when the program was launched diff --git a/barraider-sdtools/Payloads/TitleParametersPayload.cs b/barraider-sdtools/Payloads/TitleParametersPayload.cs index 64e3dee..9921e0a 100644 --- a/barraider-sdtools/Payloads/TitleParametersPayload.cs +++ b/barraider-sdtools/Payloads/TitleParametersPayload.cs @@ -12,6 +12,8 @@ namespace BarRaider.SdTools.Payloads /// public class TitleParametersPayload { + private TitleParameters titleParameters = null; + /// /// Settings JSON Object /// @@ -39,8 +41,34 @@ public class TitleParametersPayload /// /// Title Parameters /// + [JsonIgnore] + public TitleParameters TitleParameters + { + get + { + if (titleParameters != null) + { + return titleParameters; + } + + if (TitleParametersRaw != null) + { + titleParameters = new TitleParameters(TitleParametersRaw.FontFamily, TitleParametersRaw.FontSize, TitleParametersRaw.FontStyle, TitleParametersRaw.FontUnderline, TitleParametersRaw.ShowTitle, TitleParametersRaw.TitleAlignment, TitleParametersRaw.TitleColor); + } + + return titleParameters; + } + private set + { + titleParameters = value; + } + } + + /// + /// Raw Title Parameters (not as proper object) + /// [JsonProperty("titleParameters")] - public TitleParameters TitleParameters { get; private set; } + public TitleParametersRawPayload TitleParametersRaw { get; private set; } /// /// Constructor @@ -58,5 +86,10 @@ public TitleParametersPayload(JObject settings, KeyCoordinates coordinates, uint Title = title; TitleParameters = titleParameters; } + + /// + /// For Serilization + /// + public TitleParametersPayload() { } } } diff --git a/barraider-sdtools/Payloads/TitleParametersRawPayload.cs b/barraider-sdtools/Payloads/TitleParametersRawPayload.cs new file mode 100644 index 0000000..2d60940 --- /dev/null +++ b/barraider-sdtools/Payloads/TitleParametersRawPayload.cs @@ -0,0 +1,55 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace BarRaider.SdTools.Payloads +{ + /// + /// Raw payload for TitleParametersRawPayload event (without objects) + /// + public class TitleParametersRawPayload + { + /// + /// Name of font family + /// + [JsonProperty("fontFamily")] + public string FontFamily { get; private set; } + + /// + /// Size of font + /// + [JsonProperty("fontSize")] + public uint FontSize { get; private set; } + + /// + /// Style of font (bold, italic) + /// + [JsonProperty("fontStyle")] + public string FontStyle { get; private set; } + + /// + /// Is there an underling + /// + [JsonProperty("fontUnderline")] + public bool FontUnderline { get; private set; } + + /// + /// Should title be shown + /// + [JsonProperty("showTitle")] + public bool ShowTitle { get; private set; } + + /// + /// Alignment of title (top, middle, bottom) + /// + [JsonProperty("titleAlignment")] + public string TitleAlignment { get; private set; } + + /// + /// Color of title + /// + [JsonProperty("titleColor")] + public string TitleColor { get; private set; } + } +} diff --git a/barraider-sdtools/StreamDeckInfo/DeviceType.cs b/barraider-sdtools/StreamDeckInfo/DeviceType.cs new file mode 100644 index 0000000..61cb861 --- /dev/null +++ b/barraider-sdtools/StreamDeckInfo/DeviceType.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace BarRaider.SdTools +{ + /// + /// Type of StreamDeck hardware device, currently two are supported (classic and mini) + /// + public enum DeviceType + { + /// + /// StreamDeck classic with 15 keys + /// + StreamDeckClassic = 0, + + /// + /// StreamDeck mini with 6 keys + /// + StreamDeckMini = 1, + + /// + /// StreamDeck XL with 32 keys + /// + StreamDeckXL = 2, + + /// + /// StreamDeck Mobile version + /// + StreamDeckMobile = 3, + + /// + /// Corsair G-Keys version + /// + CorsairGKeys = 4, + + /// + /// Pedal + /// + StreamDeckPedal = 5, + + } +} diff --git a/barraider-sdtools/StreamDeckInfo/StreamDeckDeviceInfo.cs b/barraider-sdtools/StreamDeckInfo/StreamDeckDeviceInfo.cs index 943a74a..e5fc344 100644 --- a/barraider-sdtools/StreamDeckInfo/StreamDeckDeviceInfo.cs +++ b/barraider-sdtools/StreamDeckInfo/StreamDeckDeviceInfo.cs @@ -7,37 +7,6 @@ namespace BarRaider.SdTools { - /// - /// Type of StreamDeck hardware device, currently two are supported (classic and mini) - /// - public enum StreamDeckDeviceType - { - /// - /// StreamDeck classic with 15 keys - /// - StreamDeckClassic = 0, - - /// - /// StreamDeck mini with 6 keys - /// - StreamDeckMini = 1, - - /// - /// StreamDeck XL with 32 keys - /// - StreamDeckXL = 2, - - /// - /// StreamDeck Mobile version - /// - StreamDeckMobile = 3, - - /// - /// Corsair G-Keys version - /// - CorsairGKeys = 4 - } - /// /// Class which holds information on the StreamDeck hardware device /// @@ -53,7 +22,7 @@ public class StreamDeckDeviceInfo /// Type of StreamDeck hardware device /// [JsonProperty(PropertyName = "type")] - public StreamDeckDeviceType Type { get; private set; } + public DeviceType Type { get; private set; } /// /// Id of the StreamDeck hardware device @@ -67,7 +36,7 @@ public class StreamDeckDeviceInfo /// /// /// - public StreamDeckDeviceInfo(StreamDeckDeviceSize size, StreamDeckDeviceType type, string deviceId) + public StreamDeckDeviceInfo(StreamDeckDeviceSize size, DeviceType type, string deviceId) { Size = size; Type = type; diff --git a/barraider-sdtools/Tools/ExtensionMethods.cs b/barraider-sdtools/Tools/ExtensionMethods.cs index e76ef15..e43e9bc 100644 --- a/barraider-sdtools/Tools/ExtensionMethods.cs +++ b/barraider-sdtools/Tools/ExtensionMethods.cs @@ -32,60 +32,10 @@ public static bool IsCoordinatesSame(this KeyCoordinates coordinates, KeyCoordin return coordinates.Row == secondCoordinates.Row && coordinates.Column == secondCoordinates.Column; } - /// - /// Converts to a SDTools.KeyCoordinates - /// - /// - /// - public static KeyCoordinates ToKeyCoordinates(this streamdeck_client_csharp.Events.Coordinates coordinates) - { - if (coordinates == null) - { - return null; - } - - return new KeyCoordinates() { Column = coordinates.Columns, Row = coordinates.Rows }; - } - - #endregion - - #region Devices - - /// - /// Converts to a SDTools StreamDeckDeviceInfo object - /// - /// - /// - /// - public static StreamDeckDeviceInfo ToStreamDeckDeviceInfo(this streamdeck_client_csharp.Events.DeviceInfo deviceInfo, string deviceId) - { - if (deviceInfo == null) - { - return null; - } - - return new StreamDeckDeviceInfo(new StreamDeckDeviceSize(deviceInfo.Size.Rows, deviceInfo.Size.Columns), (StreamDeckDeviceType) ((int) deviceInfo.Type), deviceId); - } - #endregion #region Brushes/Colors - /// - /// Converts to an SDTools TitleParameters - /// - /// - /// - public static Wrappers.TitleParameters ToSDTitleParameters(this streamdeck_client_csharp.Events.TitleParameters titleParameters) - { - if (titleParameters == null) - { - return null; - } - - return new Wrappers.TitleParameters(titleParameters.FontFamily, titleParameters.FontSize, titleParameters.FontStyle, titleParameters.FontUnderline, titleParameters.ShowTitle, titleParameters.TitleAlignment, titleParameters.TitleColor); - } - /// /// Shows Color In Hex Format /// @@ -289,6 +239,87 @@ public static void AddTextPath(this Graphics graphics, TitleParameters titlePara } } + #endregion + + #region String + + + /// + /// /// Truncates a string to the first maxSize characters. If maxSize is less than string length, original string will be returned + /// + /// String + /// Max size for string + /// + public static string Truncate(this string str, int maxSize) + { + if (String.IsNullOrEmpty(str)) + { + return null; + } + + if (maxSize < 1) + { + return str; + } + + return str.Substring(0, Math.Min(Math.Max(0, maxSize), str.Length)); + } + + /// + /// Adds line breaks (\n) to the text to make sure it fits the key when using SetTitleAsync() + /// + /// + /// + /// + /// + /// + /// + public static string SplitToFitKey(this string str, TitleParameters titleParameters, int leftPaddingPixels = 3, int rightPaddingPixels = 3, int imageWidthPixels = 72) + { + try + { + if (titleParameters == null) + { + return str; + } + + int padding = leftPaddingPixels + rightPaddingPixels; + Font font = new Font(titleParameters.FontFamily, (float)titleParameters.FontSizeInPoints, titleParameters.FontStyle, GraphicsUnit.Pixel); + StringBuilder finalString = new StringBuilder(); + StringBuilder currentLine = new StringBuilder(); + SizeF currentLineSize; + + using (Bitmap img = new Bitmap(imageWidthPixels, imageWidthPixels)) + { + using (Graphics graphics = Graphics.FromImage(img)) + { + for (int idx = 0; idx < str.Length; idx++) + { + currentLine.Append(str[idx]); + currentLineSize = graphics.MeasureString(currentLine.ToString(), font); + if (currentLineSize.Width <= img.Width - padding) + { + finalString.Append(str[idx]); + } + else // Overflow + { + finalString.Append("\n" + str[idx]); + currentLine = new StringBuilder(str[idx].ToString()); + } + } + } + } + + return finalString.ToString(); + } + catch (Exception ex) + { + Logger.Instance.LogMessage(TracingLevel.ERROR, $"SplitStringToFit Exception: {ex}"); + return str; + } + } + + #endregion } } diff --git a/barraider-sdtools/Tools/GlobalSettingsManager.cs b/barraider-sdtools/Tools/GlobalSettingsManager.cs index 3177f8e..e41c1f7 100644 --- a/barraider-sdtools/Tools/GlobalSettingsManager.cs +++ b/barraider-sdtools/Tools/GlobalSettingsManager.cs @@ -1,8 +1,9 @@ -using Newtonsoft.Json.Linq; -using streamdeck_client_csharp; +using BarRaider.SdTools.Communication; +using BarRaider.SdTools.Communication.SDEvents; +using BarRaider.SdTools.Payloads; +using BarRaider.SdTools.Wrappers; +using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace BarRaider.SdTools @@ -23,7 +24,7 @@ public class GlobalSettingsManager private const int GET_GLOBAL_SETTINGS_DELAY_MS = 300; - private StreamDeckConnection connection; + private Communication.StreamDeckConnection connection; private readonly System.Timers.Timer tmrGetGlobalSettings = new System.Timers.Timer(); #endregion @@ -124,7 +125,7 @@ public async Task SetGlobalSettings(JObject settings, bool triggerDidReceiveGlob #region Private Methods - private void Connection_OnDidReceiveGlobalSettings(object sender, StreamDeckEventReceivedEventArgs e) + private void Connection_OnDidReceiveGlobalSettings(object sender, SDEventReceivedEventArgs e) { OnReceivedGlobalSettings?.Invoke(this, JObject.FromObject(e.Event.Payload).ToObject()); } diff --git a/barraider-sdtools/Tools/GraphicsTools.cs b/barraider-sdtools/Tools/GraphicsTools.cs index 25a85d4..a027125 100644 --- a/barraider-sdtools/Tools/GraphicsTools.cs +++ b/barraider-sdtools/Tools/GraphicsTools.cs @@ -268,7 +268,7 @@ public static string WrapStringToFitImage(string str, TitleParameters titleParam } catch (Exception ex) { - Logger.Instance.LogMessage(TracingLevel.ERROR, $"SplitStringToFit Exception: {ex}"); + Logger.Instance.LogMessage(TracingLevel.ERROR, $"WrapStringToFitImage Exception: {ex}"); return str; } } diff --git a/barraider-sdtools/Tools/PayloadExtensionMethods.cs b/barraider-sdtools/Tools/PayloadExtensionMethods.cs index 0010380..ff690df 100644 --- a/barraider-sdtools/Tools/PayloadExtensionMethods.cs +++ b/barraider-sdtools/Tools/PayloadExtensionMethods.cs @@ -1,4 +1,5 @@ -using streamdeck_client_csharp.Events; +using BarRaider.SdTools.Communication.SDEvents; +using BarRaider.SdTools.Payloads; using System; using System.Collections.Generic; using System.Text; @@ -7,13 +8,13 @@ namespace BarRaider.SdTools { internal static class PayloadExtensionMethods { - internal static string ToStringEx(this ReceiveSettingsPayload rsp) + internal static string ToStringEx(this ReceivedSettingsPayload rsp) { if (rsp == null) { return "ReceiveSettingsPayload is null!"; } - return $"IsInMultiAction: {rsp.IsInMultiAction} Coordinates: ({rsp.Coordinates?.Rows},{rsp.Coordinates?.Columns}) Settings: {rsp.Settings}"; + return $"IsInMultiAction: {rsp.IsInMultiAction} Coordinates: ({rsp.Coordinates?.Row},{rsp.Coordinates?.Column}) Settings: {rsp.Settings}"; } internal static string ToStringEx(this AppearancePayload ap) @@ -22,19 +23,19 @@ internal static string ToStringEx(this AppearancePayload ap) { return "AppearancePayload is null!"; } - return $"State: {ap.State} IsInMultiAction: {ap.IsInMultiAction} Coordinates: ({ap.Coordinates?.Rows},{ap.Coordinates?.Columns}) Settings: {ap.Settings}"; + return $"State: {ap.State} IsInMultiAction: {ap.IsInMultiAction} Coordinates: ({ap.Coordinates?.Row},{ap.Coordinates?.Column}) Settings: {ap.Settings}"; } - internal static string ToStringEx(this streamdeck_client_csharp.Events.KeyPayload kp) + internal static string ToStringEx(this KeyPayload kp) { if (kp == null) { return "KeyPayload is null!"; } - return $"State: {kp.State} IsInMultiAction: {kp.IsInMultiAction} DesiredState: {kp.UserDesiredState} Coordinates: ({kp.Coordinates?.Rows},{kp.Coordinates?.Columns}) Settings: {kp.Settings}"; + return $"State: {kp.State} IsInMultiAction: {kp.IsInMultiAction} DesiredState: {kp.UserDesiredState} Coordinates: ({kp.Coordinates?.Row},{kp.Coordinates?.Column}) Settings: {kp.Settings}"; } - internal static string ToStringEx(this ReceiveGlobalSettingsPayload gsp) + internal static string ToStringEx(this ReceivedGlobalSettingsPayload gsp) { if (gsp == null) { diff --git a/barraider-sdtools/Tools/PluginBase.cs b/barraider-sdtools/Tools/PluginBase.cs index 26ba33d..1d6999f 100644 --- a/barraider-sdtools/Tools/PluginBase.cs +++ b/barraider-sdtools/Tools/PluginBase.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using BarRaider.SdTools.Payloads; using Newtonsoft.Json.Linq; namespace BarRaider.SdTools diff --git a/barraider-sdtools/Tools/Tools.cs b/barraider-sdtools/Tools/Tools.cs index 35af714..3857b16 100644 --- a/barraider-sdtools/Tools/Tools.cs +++ b/barraider-sdtools/Tools/Tools.cs @@ -113,15 +113,15 @@ public static Image Base64StringToImage(string base64String) /// /// /// - public static int GetKeyDefaultHeight(StreamDeckDeviceType streamDeckType) + public static int GetKeyDefaultHeight(DeviceType streamDeckType) { switch (streamDeckType) { - case StreamDeckDeviceType.StreamDeckClassic: - case StreamDeckDeviceType.StreamDeckMini: - case StreamDeckDeviceType.StreamDeckMobile: + case DeviceType.StreamDeckClassic: + case DeviceType.StreamDeckMini: + case DeviceType.StreamDeckMobile: return CLASSIC_KEY_DEFAULT_HEIGHT; - case StreamDeckDeviceType.StreamDeckXL: + case DeviceType.StreamDeckXL: return XL_KEY_DEFAULT_HEIGHT; default: Logger.Instance.LogMessage(TracingLevel.ERROR, $"SDTools GetKeyDefaultHeight Error: Invalid StreamDeckDeviceType: {streamDeckType}"); @@ -136,15 +136,15 @@ public static int GetKeyDefaultHeight(StreamDeckDeviceType streamDeckType) /// /// /// - public static int GetKeyDefaultWidth(StreamDeckDeviceType streamDeckType) + public static int GetKeyDefaultWidth(DeviceType streamDeckType) { switch (streamDeckType) { - case StreamDeckDeviceType.StreamDeckClassic: - case StreamDeckDeviceType.StreamDeckMini: - case StreamDeckDeviceType.StreamDeckMobile: + case DeviceType.StreamDeckClassic: + case DeviceType.StreamDeckMini: + case DeviceType.StreamDeckMobile: return CLASSIC_KEY_DEFAULT_WIDTH; - case StreamDeckDeviceType.StreamDeckXL: + case DeviceType.StreamDeckXL: return XL_KEY_DEFAULT_WIDTH; default: Logger.Instance.LogMessage(TracingLevel.ERROR, $"SDTools GetKeyDefaultHeight Error: Invalid StreamDeckDeviceType: {streamDeckType}"); @@ -160,7 +160,7 @@ public static int GetKeyDefaultWidth(StreamDeckDeviceType streamDeckType) /// /// /// - public static Bitmap GenerateKeyImage(StreamDeckDeviceType streamDeckType, out Graphics graphics) + public static Bitmap GenerateKeyImage(DeviceType streamDeckType, out Graphics graphics) { int height = GetKeyDefaultHeight(streamDeckType); int width = GetKeyDefaultWidth(streamDeckType); @@ -305,7 +305,7 @@ public static string FormatBytes(double numberInBytes) } /// - /// Adds line breaks (\n) to the text to make sure it fits the key when using SetTitleAsync() + /// OBSOLETE - Use String.SplitToFitKey() from SdTools.ExtensionMethods /// /// /// @@ -313,49 +313,10 @@ public static string FormatBytes(double numberInBytes) /// /// /// + [Obsolete("Use String.SplitToFitKey(), now part of the SdTools.ExtensionMethods")] public static string SplitStringToFit(string str, TitleParameters titleParameters, int leftPaddingPixels = 3, int rightPaddingPixels = 3, int imageWidthPixels = 72) { - try - { - if (titleParameters == null) - { - return str; - } - - int padding = leftPaddingPixels + rightPaddingPixels; - Font font = new Font(titleParameters.FontFamily, (float)titleParameters.FontSizeInPoints, titleParameters.FontStyle, GraphicsUnit.Pixel); - StringBuilder finalString = new StringBuilder(); - StringBuilder currentLine = new StringBuilder(); - SizeF currentLineSize; - - using (Bitmap img = new Bitmap(imageWidthPixels, imageWidthPixels)) - { - using (Graphics graphics = Graphics.FromImage(img)) - { - for (int idx = 0; idx < str.Length; idx++) - { - currentLine.Append(str[idx]); - currentLineSize = graphics.MeasureString(currentLine.ToString(), font); - if (currentLineSize.Width <= img.Width - padding) - { - finalString.Append(str[idx]); - } - else // Overflow - { - finalString.Append("\n" + str[idx]); - currentLine = new StringBuilder(str[idx].ToString()); - } - } - } - } - - return finalString.ToString(); - } - catch (Exception ex) - { - Logger.Instance.LogMessage(TracingLevel.ERROR, $"SplitStringToFit Exception: {ex}"); - return str; - } + return str.SplitToFitKey(titleParameters, leftPaddingPixels, rightPaddingPixels, imageWidthPixels); } #endregion diff --git a/barraider-sdtools/Wrappers/Coordinates.cs b/barraider-sdtools/Wrappers/KeyCoordinates.cs similarity index 100% rename from barraider-sdtools/Wrappers/Coordinates.cs rename to barraider-sdtools/Wrappers/KeyCoordinates.cs diff --git a/barraider-sdtools/Wrappers/TitleParameters.cs b/barraider-sdtools/Wrappers/TitleParameters.cs index 7deb4f9..5641784 100644 --- a/barraider-sdtools/Wrappers/TitleParameters.cs +++ b/barraider-sdtools/Wrappers/TitleParameters.cs @@ -35,6 +35,7 @@ public class TitleParameters #region Private Members private const double POINTS_TO_PIXEL_CONVERT = 1.3; private const int DEFAULT_IMAGE_SIZE_FONT_SCALE = 3; + private const string DEFAULT_FONT_FAMILY_NAME = "Verdana"; #endregion /// @@ -60,12 +61,12 @@ public class TitleParameters /// [JsonIgnore] public double FontSizeInPixelsScaledToDefaultImage => Math.Round(FontSizeInPixels * DEFAULT_IMAGE_SIZE_FONT_SCALE); - + /// /// Font Family /// [JsonProperty("fontFamily")] - public FontFamily FontFamily { get; private set; } = new FontFamily("Verdana"); + public FontFamily FontFamily { get; private set; } = new FontFamily(DEFAULT_FONT_FAMILY_NAME); /// /// Font Style @@ -119,6 +120,7 @@ public TitleParameters(string fontFamily, uint fontSize, string fontStyle, bool ParsePayload(fontFamily, fontSize, fontStyle, fontUnderline, showTitle, titleAlignment, titleColor); } + private void ParsePayload(string fontFamily, uint fontSize, string fontStyle, bool fontUnderline, bool showTitle, string titleAlignment, string titleColor) { try @@ -153,6 +155,9 @@ private void ParsePayload(string fontFamily, uint fontSize, string fontStyle, bo case "bold italic": FontStyle = FontStyle.Bold | FontStyle.Italic; break; + default: + Logger.Instance.LogMessage(TracingLevel.ERROR, $"{this.GetType()} Cannot parse Font Style: {fontStyle}"); + break; } } if (fontUnderline) @@ -178,7 +183,7 @@ private void ParsePayload(string fontFamily, uint fontSize, string fontStyle, bo } catch (Exception ex) { - Logger.Instance.LogMessage(TracingLevel.ERROR, $"TitleParser failed to parse payload {ex}"); + Logger.Instance.LogMessage(TracingLevel.ERROR, $"TitleParameters failed to parse payload {ex}"); } } } diff --git a/barraider-sdtools/barraider-sdtools.csproj b/barraider-sdtools/barraider-sdtools.csproj index 8d4554e..69c2376 100644 --- a/barraider-sdtools/barraider-sdtools.csproj +++ b/barraider-sdtools/barraider-sdtools.csproj @@ -16,12 +16,12 @@ Feel free to contact me for more information: https://barraider.comStreamDeck Elgato Library Plugin Stream Deck Toolkit StreamDeck-Tools - 3.2.0.0 - 3.2.0.0 - 3.2 - 3.2 - 1. Created new ISDConnection interface which is now implemented by SDConnection and used by PluginAction. -2. GlobalSettingsManager now has a short delay before calling GetGlobalSettings, to reduce spamming the Stream Deck SDK. -3. Updated dependencies to latest version + 3.9.0.0 + 3.9.0.0 + 3.9.1 + 4.0 - 1. Merged streamdeck-client-csharp package into library to allow better logging of errors +2. Increased timeout of connection to Stream Deck due to the Stream Deck taking longer than before to reply on load +3. Added error catching to prevent 3rd party plugin exception to impact communication BarRaider.SdTools StreamDeckTools @@ -34,10 +34,10 @@ Feel free to contact me for more information: https://barraider.comstreamdeck-tools.xml - + - - + + diff --git a/barraider-sdtools/streamdeck-tools.xml b/barraider-sdtools/streamdeck-tools.xml new file mode 100644 index 0000000..b61028e --- /dev/null +++ b/barraider-sdtools/streamdeck-tools.xml @@ -0,0 +1,2187 @@ + + + + StreamDeckTools + + + + + FilenamePropertyAttribute - Used to indicate the current property holds a file name. + This will allow StreamDeck Tools to strip the mandatory "C:\fakepath\" added by the SDK + + + + + PluginActionId attribute + Used to indicate the UUID in the manifest file that matches to this class + + + + + UUID of the action + + + + + Constructor - This attribute is used to indicate the UUID in the manifest file that matches to this class + + + + + + Interface for a Stream Deck connection + + + + + Event received by the plugin when the Property Inspector uses the sendToPlugin event. + + + + + Event received when the user changes the title or title parameters. + + + + + Event received when a monitored application is terminated + + + + + Event received when a monitored application is launched + + + + + Event received when a device is unplugged from the computer + + + + + Event received when a device is plugged to the computer. + + + + + Event received when the Property Inspector appears in the Stream Deck software user interface, for example when selecting a new instance. + + + + + Event received when the Property Inspector for an instance is removed from the Stream Deck software user interface, for example when selecting a different instance. + + + + + Event received when the computer wakes up + + + + + Send settings to the PropertyInspector + + + + + + + Persists your plugin settings + + + + + + + Persists your global plugin settings + + Settings to save globally + Boolean whether to also trigger a didReceiveGlobalSettings event. Default is true + + + + + Persists your global plugin settings + + + + + + Sets an image on the StreamDeck key. + + Base64 encoded image + A 0-based integer value representing the state of an action with multiple states. This is an optional parameter. If not specified, the title is set to all states. + Should image be sent even if it is identical to the one sent previously. Default is false + + + + + Sets an image on the StreamDeck key + + Image object + A 0-based integer value representing the state of an action with multiple states. This is an optional parameter. If not specified, the title is set to all states. + Should image be sent even if it is identical to the one sent previously. Default is false + + + + + Sets the default image for this state, as configured in the manifest + + + + + + Sets a title on the StreamDeck key + + + A 0-based integer value representing the state of an action with multiple states. This is an optional parameter. If not specified, the title is set to all states. + + + + + Switches to one of the plugin's built-in profiles + + + + + + + Switches to one of the plugin's built-in profiles. Allows to choose which device to switch it on. + + + + + + + + Shows the Alert (Yellow Triangle) on the StreamDeck key + + + + + + Shows the Success (Green checkmark) on the StreamDeck key + + + + + + Add a message to the Stream Deck log. This is the log located at: %appdata%\Elgato\StreamDeck\logs\StreamDeck0.log + + + + + + + Gets the Stream Deck device's info + + + + + + Tells Stream Deck to return the current plugin settings via the ReceivedSettings function + + + + + + Opens a URI in the user's browser + + + + + + + Opens a URI in the user's browser + + + + + + + Sets the plugin to a specific state which is pre-configured in the manifest file + + + + + + + An opaque value identifying the plugin. This value is received during the Registration procedure + + + + + An opaque value identifying the device the plugin is launched on. + + + + + StreamDeckConnection object, initialized based on the args received when launching the program + + + + + Connection object which handles your communication with the Stream Deck app + + + + + An opaque value identifying the plugin. Received as an argument when the executable was launched. + + + + + Holds information about the devices connected to the computer + + + + + Event received by the plugin when the Property Inspector uses the sendToPlugin event. + + + + + Event received when the user changes the title or title parameters. + + + + + Event received when a monitored application is terminated + + + + + Event received when a monitored application is launched + + + + + Event received when a device is unplugged from the computer + + + + + Event received when a device is plugged to the computer. + + + + + Event received when the Property Inspector appears in the Stream Deck software user interface, for example when selecting a new instance. + + + + + Event received when the Property Inspector for an instance is removed from the Stream Deck software user interface, for example when selecting a different instance. + + + + + Event received when the computer wakes up + + + + + Send settings to the PropertyInspector + + + + + + + Persists your plugin settings + + + + + + + Persists your global plugin settings + + Settings to save globally + Boolean whether to also trigger a didReceiveGlobalSettings event. Default is true + + + + + Persists your global plugin settings + + + + + + Sets an image on the StreamDeck key. + + Base64 encoded image + A 0-based integer value representing the state of an action with multiple states. This is an optional parameter. If not specified, the title is set to all states. + Should image be sent even if it is identical to the one sent previously. Default is false + + + + + Sets an image on the StreamDeck key + + Image object + A 0-based integer value representing the state of an action with multiple states. This is an optional parameter. If not specified, the title is set to all states. + Should image be sent even if it is identical to the one sent previously. Default is false + + + + + Sets the default image for this state, as configured in the manifest + + + + + + Sets a title on the StreamDeck key + + + A 0-based integer value representing the state of an action with multiple states. This is an optional parameter. If not specified, the title is set to all states. + + + + + Switches to one of the plugin's built-in profiles + + + + + + + Switches to one of the plugin's built-in profiles. Allows to choose which device to switch it on. + + + + + + + + Shows the Alert (Yellow Triangle) on the StreamDeck key + + + + + + Shows the Success (Green checkmark) on the StreamDeck key + + + + + + Add a message to the Stream Deck log. This is the log located at: %appdata%\Elgato\StreamDeck\logs\StreamDeck0.log + + + + + + + Gets the Stream Deck device's info + + + + + + Tells Stream Deck to return the current plugin settings via the ReceivedSettings function + + + + + + Opens a URI in the user's browser + + + + + + + Opens a URI in the user's browser + + + + + + + Sets the plugin to a specific state which is pre-configured in the manifest file + + + + + + + An opaque value identifying the plugin. This value is received during the Registration procedure + + + + + An opaque value identifying the device the plugin is launched on. + + + + + StreamDeckConnection object, initialized based on the args received when launching the program + + + + + Public constructor, a StreamDeckConnection object is required along with the current action and context IDs + These will be used to correctly communicate with the StreamDeck App + + + + + + + /// + + + + Dispose (Destructor) function + + + + + * Easy Configuration Instructions: + * 1. Use NuGet to get the following packages: + * CommandLineParser by gsscoder + * streamdeck-client-csharp by Shane DeSeranno + * Newtonsoft.Json by James Newton-King + * 2. Create a class that implements the IPluginable interface (which is located in BarRaider.SDTools), this will be your main plugin + * 3. Pass the type of the class to the main function + + + + /************************************************************************ + * Initial configuration from TyrenDe's streamdeck-client-csharp example: + * https://github.com/TyrenDe/streamdeck-client-csharp + * and SaviorXTanren's MixItUp.StreamDeckPlugin: + * https://github.com/SaviorXTanren/mixer-mixitup/ + *************************************************************************/ + + Library's main initialization point. + Pass the args from your Main function. We'll handle the rest + + + + + + Library's main initialization point. + Pass the args from your Main function and a list of supported PluginActionIds, the framework will handle the rest. + + + + + + + Empty payload in event + + + + + Payload for Apperance settings + + + + + Additional settings + + + + + Coordinates of key pressed + + + + + State of key + + + + + Is action in MultiAction + + + + + Payload for ApplicationDidLaunch event + + + + + Application information + + + + + Payload for ApplicationDidTerminate Event + + + + + Application payload + + + + + List of all supported event typs + + + + + Base event that all the actual events derive from + + + + + Name of the event raised + + + + + Payload for DeviceDidConnect Event + + + + + UUID of device + + + + + Information on the device connected + + + + + Payload for DeviceDidDisconnect Event + + + + + UUID of device that was disconnected + + + + + Payload for DidReceiveGlobalSettings Event + + + + + Global Settings payload + + + + + Payload for DidReceiveSettings Event + + + + + Action Name + + + + + Context (unique action UUID) + + + + + Device UUID action is on + + + + + Settings for action + + + + + Payload for KeyDown event + + + + + Action Name + + + + + Unique Action UUID + + + + + Device UUID key was pressed on + + + + + Information on key + + + + + Payload for KeyUp event + + + + + Action name + + + + + Unique action UUID + + + + + Stream Deck device UUID + + + + + Key settings + + + + + Payload for PropertyInspectorDidAppearEvent event + + + + + Action Name + + + + + Unique Action UUID + + + + + Stream Deck device UUID + + + + + Payload for PropertyInspectorDidDisappearEvent event + + + + + Action Name + + + + + Unique Action UUID + + + + + Stream Deck device UUID + + + + + Payload for SendToPluginEvent event + + + + + Action Name + + + + + Unique Action UUID + + + + + Payload + + + + + Payload for SystemDidWakeUp event + + + + + Payload for TitleParametersDidChangeEvent event + + + + + Action Name + + + + + Unique Action UUID + + + + + Stream Deck device UUID + + + + + Title settings + + + + + Payload for WillAppearEvent event + + + + + Action Name + + + + + Unique Action UUID + + + + + Stream Deck device UUID + + + + + Appearance settings + + + + + Payload for WillDisappearEvent event + + + + + Action Name + + + + + Unique Action UUID + + + + + Stream Deck device UUID + + + + + settings + + + + + Target to send Title/Image to + + + + + Send to both App and Device + + + + + Send only to device + + + + + Send only to app + + + + + Underlying object that communicates with the stream deck app + + + + + The port used to connect to the StreamDeck websocket + + + + + This is the unique identifier used to communicate with the register StreamDeck plugin. + + + + + Raised when plugin is connected to stream deck app + + + + + /// Raised when plugin is disconnected from stream deck app + + + + + Raised when key is pushed down + + + + + Raised when key is released + + + + + Raised when the action is shown, main trigger for a PluginAction + + + + + Raised when the action is no longer shown, main trigger for Dispose of PluginAction + + + + + Contains information on the Title and its style + + + + + Raised when a Stream Deck device is connected to the PC + + + + + Raised when a Stream Deck device has disconnected from the PC + + + + + Raised when a monitored app is launched/active + + + + + Raised when a monitored app is terminated + + + + + Raised after the PC wakes up from sleep + + + + + Raised when settings for the action are received + + + + + Raised when global settings for the entire plugin are received + + + + + Raised when the user is viewing the settings in the Stream Deck app + + + + + Raised when the user stops viewing the settings in the Stream Deck app + + + + + Raised when a payload is sent to the plugin from the PI + + + + + Payload for ApplicationDidLaunch event + + + + + Payload + + + + + Constructor + + + + + + Payload for ApplicationDidTerminate event + + + + + Payload + + + + + Constructor + + + + + + Payload for DeviceDidConnect event + + + + + Device GUID + + + + + Device Info + + + + + Constructor + + + + + + Payload for DeviceDidDisconnect event + + + + + Device GUID + + + + + Constructor + + + + + + Payload for PropertyInspectorDidAppear event + + + + + ActionId + + + + + ContextId + + + + + Device Guid + + + + + Constructor + + + + + + + + Payload for PropertyInspectorDidDisappear event + + + + + Action Id + + + + + ContextId + + + + + Device Guid + + + + + Constructor + + + + + + + + Payload for SendToPlugin event + + + + + ActionId + + + + + ContextId + + + + + Payload + + + + + Constructor + + + + + + + + Payload for SystemDidWakeUp event + + + + + Constructor + + + + + Payload for TitleParametersDidChange event + + + + + Action Id + + + + + Context Id + + + + + Device Guid + + + + + Payload + + + + + Constructor + + + + + + + + + ApplicationPayload + + + + + Application Name + + + + + Constructor + + + + + + Class holding all the information passed to the plugin when the program was launched + + + + + Port to communicate with the StreamDeck app + + + + + UUID of the plugin + + + + + Name of the event we should pass to the StreamDeck app to register + + + + + Raw information in JSON format which we will parse into the DeviceInfo property + + + + + Information regarding the StreamDeck app and StreamDeck hardware which was parsed from the RawInfo JSON field. + + + + + Payload for TitleParametersDidChange Event + + + + + Settings JSON Object + + + + + Key Coordinates + + + + + Key State + + + + + Title + + + + + Title Parameters + + + + + Raw Title Parameters (not as proper object) + + + + + Constructor + + + + + + + + + + For Serilization + + + + + Raw payload for TitleParametersRawPayload event (without objects) + + + + + Name of font family + + + + + Size of font + + + + + Style of font (bold, italic) + + + + + Is there an underling + + + + + Should title be shown + + + + + Alignment of title (top, middle, bottom) + + + + + Color of title + + + + + Payload received during the plugin's constructor + + + + + Plugin instance's settings (set through Property Inspector) + + + + + Plugin's physical location on the Stream Deck device + + + + + Current plugin state + + + + + Is it in a Multiaction + + + + + Information regarding the Stream Deck hardware device + + + + + Constructor + + + + + + + + + + Payload received when a key is pressed or released + + + + + Current plugin settings + + + + + Location of plugin on the stream deck + + + + + Current plugin state + + + + + Desired state + + + + + Is part of a multiAction + + + + + Constructor + + + + + + + + + + For Seralization + + + + + Payload that holds all the settings in the ReceivedGlobalSettings event + + + + + Global settings object + + + + + Payload that holds all the settings in the ReceivedSettings event + + + + + Action's settings + + + + + Coordinates of the key pressed + + + + + Is event part of a multiaction + + + + + Type of StreamDeck hardware device, currently two are supported (classic and mini) + + + + + StreamDeck classic with 15 keys + + + + + StreamDeck mini with 6 keys + + + + + StreamDeck XL with 32 keys + + + + + StreamDeck Mobile version + + + + + Corsair G-Keys version + + + + + Pedal + + + + + Corsair CUE SDK (?) + + + + + Stream Deck+ + + + + + Holds general information on the StreamDeck App we're communicating with + + + + + Current language of the StreamDeck app + + + + + OS Platform + + + + + Current version of the StreamDeck app + + + + + Shows class information as string + + + + + + Class which holds information on the StreamDeck hardware device + + + + + Details on number of keys of the StreamDeck hardware device + + + + + Type of StreamDeck hardware device + + + + + Id of the StreamDeck hardware device + + + + + Constructor + + + + + + + + Shows class information as string + + + + + + Layout of the keys on the StreamDeck hardware device + + + + + Number of key rows on the StreamDeck hardware device + + + + + Number of key columns on the StreamDeck hardware device + + + + + Constructor + + + + + + + Shows class information as string + + + + + + Class which holds information on the StreamDeck app and StreamDeck hardware device that the plugin is communicating with + + + + + Information on the StreamDeck App which we're communicating with + + + + + Information on the StreamDeck hardware device that the plugin is running on + + + + + Information on the Plugin we're currently running + + + + + Device pixel ratio + + + + + Shows class information as string + + + + + + Holds general information on the StreamDeck App we're communicating with + + + + + Current version of the plugin + + + + + Shows class information as string + + + + + + Extension methods for various objects + + + + + Checks if too KeyCoordinates match to the same key + + + + + + + + Shows Color In Hex Format + + + + + + + Shows Color in Hex format + + + + + + + Converts an Image into a Byte Array + + + + + + + Draws a string on a Graphics object and returns the ending Y position of the string + + + + + + + + + + + Returns the center X position of a string, given the image's max Width and Font information + + + + + + /// True/False - Does text fit image? False if text overflows + + + + + + + Returns the center X position of a string, given the image's max Width and Font information + + + + + + + + + + + + Returns the highest size of the given font in which the text fits the image + + + + + + /// + + + + + Adds a text path to an existing Graphics object. Uses TitleParameters to emulate the Text settings in the Property Inspector + + + + + + + + + + + Adds a text path to an existing Graphics object. Uses TitleParameters to emulate the Text settings in the Property Inspector + + + + + + + + + + + + + /// Truncates a string to the first maxSize characters. If maxSize is less than string length, original string will be returned + + String + Max size for string + + + + + Adds line breaks (\n) to the text to make sure it fits the key when using SetTitleAsync() + + + + + + + + + + + Helper class which allows fetching the GlobalSettings of a plugin + + + + + Returns singelton entry of GlobalSettingsManager + + + + + Event triggered when Global Settings are received + + + + + Command to request the Global Settings. Use the OnDidReceiveGlobalSSettings callback function to receive the Global Settings. + + + + + + Sets the Global Settings for the plugin + + + + + + + + Library of tools used to manipulate graphics + + + + + Return a Color object based on the hex value + + + + + + + Generates multiple shades based on an initial color, and number of stages/shades you want + + + + + + + + + Resizes an image while scaling + + + + + + + + + Extract a part of an Image + + + + + + + + + + + Creates a new image with different opacity + + + + + + + + Generates one (or more) images where each one has a few letters drawn on them based on the parameters. You can set number of letters and number of lines per key. + Use expandToNextImage to decide if you want only one Image returned or multiple if text is too long for one key + + + + + + + + + + + + + + + Adds line breaks ('\n') to the string every time the text would overflow the image + + + + + + + + + + + Tracing levels used for Logger + + + + + Debug level + + + + + Informational level + + + + + Warning level + + + + + Error level + + + + + Fatal (highest) level + + + + + Log4Net logger helper class + + + + + Returns singelton entry of Log4Net logger + + + + + Add message to log with a specific severity level. + + + + + + + Main abstract class your plugin should derive from + Holds implementation for all the basic functions + If you're missing an event, you can register to it from the Connection.StreamDeckConnection object + + + + + Called when a Stream Deck key is pressed + + + + + Called when a Stream Deck key is released + + + + + Called when the PropertyInspector has new settings + + + + + + Called when GetGlobalSettings is called. + + + + + + Called every second + Logic for displaying title/image can go here + + + + + Abstract method Called when the plugin is disposed + + + + + Main iDisposable Dispose function + + + + + Connection object which handles your communication with the Stream Deck app + + + + + Constructor for PluginBase. Receives the communication and plugin settings + Note that the settings object is not used by the base and should be consumed by the deriving class. + Usually, a private class inside the deriving class is created which stores the settings + Example for settings usage: + * if (payload.Settings == null || payload.Settings.Count == 0) + * { + * // Create default settings + * } + * else + * { + this.settings = payload.Settings.ToObject(); + * } + + + Communication module with Stream Deck + Plugin settings - NOTE: Not used in base class, should be consumed by deriving class + + + + Helper class for generating random numbers + + + + + Returns a non-negative random integer that is less than the specified maximum. + + + + + + + Returns a random integer that is within a specified range. Value will be less than the specified maximum. + + + + + + + + Set of common utilities used by various plugins + Currently the class mostly focuses on image-related functions that will be passed to the StreamDeck key + + + + + Convert an image file to Base64 format. Set the addHeaderPrefix to true, if this is sent to the SendImageAsync function + + + + + + + + Convert a in-memory image object to Base64 format. Set the addHeaderPrefix to true, if this is sent to the SendImageAsync function + + + + + + + + Convert a base64 image string to an Image object + + + + + + + Gets the key default height in pixels. + To get the StreamDeckType use Connection.DeviceInfo() + + + + + + + Gets the key default width in pixels. + To get the StreamDeckType use Connection.DeviceInfo() + + + + + + + Generates an empty key bitmap with the default height and width. + New: To get the StreamDeckType use Connection.DeviceInfo() + + + + + + + + Creates a key image that fits all Stream Decks + + + + + + + Creates a key image based on given height and width + + + + + + + + + Deprecated! Use AddTextPath on the Graphics extension method instead. + Adds a text path to an existing Graphics object. Uses TitleParser to emulate the Text settings in the Property Inspector + + + + + + + + + + + Extracts the actual filename from a file payload received from the Property Inspector + + + + + + + Converts a long to a human-readable string. Example: 54,265 => 54.27k + + + + + + Size in bytes + Formatted human-readable string (ex. "2 MB") + + + + OBSOLETE - Use String.SplitToFitKey() from SdTools.ExtensionMethods + + + + + + + + + + + Returns SHA512 Hash from an image object + + + + + + + Returns SHA512 Hash from a string + + + + + + + Returns SHA512 Hash from a byte stream + + + + + + + Iterates through the fromJObject, finds the property that matches in the toSettings object, and sets the value from the fromJObject object + + + + + Number of properties updated + + + + Uses the PluginActionId attribute on the various classes derived from PluginBase to find all the actions supported in this assembly + + + + + + Coordinates of the current key + + + + + Column of the current key + + + + + Row of the current key + + + + + This class associates a plugin UUID (which is indicated in the Manifest file), with the type of the implementation class. + The implementation class must be derived from the PluginBase class for this to work properly. + If the type passed does not derrive from PluginBase, a NotSupportedException will be thrown + + + + + Action UUID as indicated in the manifest file + + + + + Type of class that implemented this action. Must inherit PluginBase + + + + + PluginActionId constructor + + actionId is the UUID from the manifest file + Type of class that implemented this action. Must inherit PluginBase + + + + Base (Generic) EventArgs used for events + + + + + + Event Information + + + + + Enum for the alignment of the Title text on the key + + + + + Top Alignment + + + + + Middle/Center Alignment + + + + + Bottom Alignment + + + + + Class holding all the Title Information set by a user in the Property Inspector + + + + + Title Color + + + + + Font Size in Points + + + + + Font Size in Pixels + + + + + Font Size Scaled to Image + + + + + Font Family + + + + + Font Style + + + + + Should Title be shown + + + + + Alignment position of the Title text on the key + + + + + Constructor + + + + + + + + + + + Constructor + + + + + + + + + + + diff --git a/streamdeck-tools.xml b/streamdeck-tools.xml index 57f7a0b..c0f8f89 100644 --- a/streamdeck-tools.xml +++ b/streamdeck-tools.xml @@ -1136,6 +1136,25 @@ + + + /// Truncates a string to the first maxSize characters. If maxSize is less than string length, original string will be returned + + String + Max size for string + + + + + Adds line breaks (\n) to the text to make sure it fits the key when using SetTitleAsync() + + + + + + + + Helper class which allows fetching the GlobalSettings of a plugin @@ -1479,7 +1498,7 @@ - Adds line breaks (\n) to the text to make sure it fits the key when using SetTitleAsync() + OBSOLETE - Use String.SplitToFitKey() from SdTools.ExtensionMethods